Skip to content

Commit

Permalink
Allow codecs and parameters in wav and raw export
Browse files Browse the repository at this point in the history
  • Loading branch information
chussong committed Jun 7, 2019
1 parent f181b3f commit bc2639c
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 6 deletions.
20 changes: 14 additions & 6 deletions pydub/audio_segment.py
Original file line number Diff line number Diff line change
Expand Up @@ -767,15 +767,15 @@ def export(self, out_f=None, format='mp3', codec=None, bitrate=None, parameters=
('mp3', 'wav', 'raw', 'ogg' or other ffmpeg/avconv supported files)
codec (string)
Codec used to encoding for the destination.
Codec used to encode the destination file.
bitrate (string)
Bitrate used when encoding destination file. (64, 92, 128, 256, 312k...)
Each codec accepts different bitrate arguments so take a look at the
ffmpeg documentation for details (bitrate usually shown as -b, -ba or
-a:b).
parameters (string)
parameters (list of strings)
Aditional ffmpeg/avconv parameters
tags (dict)
Expand All @@ -790,6 +790,12 @@ def export(self, out_f=None, format='mp3', codec=None, bitrate=None, parameters=
"""
id3v2_allowed_versions = ['3', '4']

if format == "raw" and (codec is not None or parameters is not None):
raise AttributeError(
'Can not invoke ffmpeg when export format is "raw"; '
'specify an ffmpeg raw format like format="s16le" instead '
'or call export(format="raw") with no codec or parameters')

out_f, _ = _fd_or_path_or_tempfile(out_f, 'wb+')
out_f.seek(0)

Expand All @@ -798,8 +804,10 @@ def export(self, out_f=None, format='mp3', codec=None, bitrate=None, parameters=
out_f.seek(0)
return out_f

# for wav output we can just write the data directly to out_f
if format == "wav":
# wav with no ffmpeg parameters can just be written directly to out_f
easy_wav = format == "wav" and codec is None and parameters is None

if easy_wav:
data = out_f
else:
data = NamedTemporaryFile(mode="wb", delete=False)
Expand All @@ -814,8 +822,8 @@ def export(self, out_f=None, format='mp3', codec=None, bitrate=None, parameters=
wave_data.writeframesraw(self._data)
wave_data.close()

# for wav files, we're done (wav data is written directly to out_f)
if format == 'wav':
# for easy wav files, we're done (wav data is written directly to out_f)
if easy_wav:
return out_f

output = NamedTemporaryFile(mode="w+b", delete=False)
Expand Down
31 changes: 31 additions & 0 deletions test/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -560,6 +560,27 @@ def test_export_as_wav(self):
len(seg),
percentage=0.01)

def test_export_as_wav_with_codec(self):
seg = self.seg1
exported_wav = seg.export(format='wav', codec='pcm_s32le')
seg_exported_wav = AudioSegment.from_wav(exported_wav)

self.assertWithinTolerance(len(seg_exported_wav),
len(seg),
percentage=0.01)
self.assertEqual(seg_exported_wav.sample_width, 4)

def test_export_as_wav_with_parameters(self):
seg = self.seg1
exported_wav = seg.export(format='wav', parameters=['-ar', '16000', '-ac', '1'])
seg_exported_wav = AudioSegment.from_wav(exported_wav)

self.assertWithinTolerance(len(seg_exported_wav),
len(seg),
percentage=0.01)
self.assertEqual(seg_exported_wav.frame_rate, 16000)
self.assertEqual(seg_exported_wav.channels, 1)

def test_export_as_raw(self):
seg = self.seg1
exported_raw = seg.export(format='raw')
Expand All @@ -570,6 +591,16 @@ def test_export_as_raw(self):
len(seg),
percentage=0.01)

def test_export_as_raw_with_codec(self):
seg = self.seg1
with self.assertRaises(AttributeError):
seg.export(format='raw', codec='pcm_s32le')

def test_export_as_raw_with_parameters(self):
seg = self.seg1
with self.assertRaises(AttributeError):
seg.export(format='raw', parameters=['-ar', '16000', '-ac', '1'])

def test_export_as_ogg(self):
seg = self.seg1
exported_ogg = seg.export(format='ogg')
Expand Down

0 comments on commit bc2639c

Please sign in to comment.