forked from pool/python-pydub
- Enable tests. Changed source to the github release, which also removes the need to provide a copy of the LICENSE file. - Add 0001-Skip-tests-that-use-unavailable-codecs.patch to skip tests that use codecs not supported by the official ffmpeg package - Update to 0.23.1 * Fix bug in passing ffmpeg/avconv parameters for pydub.AudioSegment.from_mp3(), pydub.AudioSegment.from_flv(), pydub.AudioSegment.from_ogg() and pydub.AudioSegment.from_wav() * Fix logic bug in pydub.effects.strip_silence() OBS-URL: https://build.opensuse.org/request/show/677638 OBS-URL: https://build.opensuse.org/package/show/devel:languages:python/python-pydub?expand=0&rev=11
196 lines
7.2 KiB
Diff
196 lines
7.2 KiB
Diff
From 01383a88fe6bd574e3e47547ee6b7828af52a344 Mon Sep 17 00:00:00 2001
|
|
From: Antonio Larrosa <antonio.larrosa@gmail.com>
|
|
Date: Tue, 19 Feb 2019 20:01:39 +0100
|
|
Subject: [PATCH] Skip tests that use unavailable codecs
|
|
|
|
In openSUSE, ffmpeg doesn't support aac audio and some other codecs due
|
|
to legal reasons. When building the pydub packages and running tests,
|
|
some of these fail because the files format_test.m4a, creative_common.mp4
|
|
wrong_extension.aac can't be read since they use aac audio.
|
|
|
|
This commit adds two functions get_supported_decoders and
|
|
get_supported_encoders that return a set with the decoders/encoders that
|
|
are supported. Then it also adds some decorators to the tests to skip
|
|
the tests that use unsupported codecs.
|
|
|
|
Note that functools.lru_cache was added in python 3.3, so it can't be
|
|
used and that's the reason I added a small implementation of a cache
|
|
decorator so we don't have to execute ffmpeg for every call to get
|
|
the supported codecs.
|
|
|
|
https://github.com/jiaaro/pydub/pull/362
|
|
---
|
|
pydub/utils.py | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
test/test.py | 22 ++++++++++++++++++++
|
|
2 files changed, 76 insertions(+)
|
|
|
|
diff --git a/pydub/utils.py b/pydub/utils.py
|
|
index def1a72..8cf0262 100644
|
|
--- a/pydub/utils.py
|
|
+++ b/pydub/utils.py
|
|
@@ -8,6 +8,7 @@ from subprocess import Popen, PIPE
|
|
from math import log, ceil
|
|
from tempfile import TemporaryFile
|
|
from warnings import warn
|
|
+from functools import wraps
|
|
|
|
try:
|
|
import audioop
|
|
@@ -351,3 +352,56 @@ def mediainfo(filepath):
|
|
info[key] = value
|
|
|
|
return info
|
|
+
|
|
+
|
|
+def cache_codecs(function):
|
|
+ cache = {}
|
|
+
|
|
+ @wraps(function)
|
|
+ def wrapper():
|
|
+ try:
|
|
+ return cache[0]
|
|
+ except:
|
|
+ cache[0] = function()
|
|
+ return cache[0]
|
|
+
|
|
+ return wrapper
|
|
+
|
|
+
|
|
+@cache_codecs
|
|
+def get_supported_codecs():
|
|
+ encoder = get_encoder_name()
|
|
+ command = [encoder, "-codecs"]
|
|
+ res = Popen(command, stdout=PIPE, stderr=PIPE)
|
|
+ output = res.communicate()[0].decode("utf-8")
|
|
+ if res.returncode != 0:
|
|
+ return []
|
|
+
|
|
+ if sys.platform == 'win32':
|
|
+ output = output.replace("\r", "")
|
|
+
|
|
+
|
|
+ rgx = re.compile(r"^([D.][E.][AVS.][I.][L.][S.]) (\w*) +(.*)")
|
|
+ decoders = set()
|
|
+ encoders = set()
|
|
+ for line in output.split('\n'):
|
|
+ match = rgx.match(line.strip())
|
|
+ if not match:
|
|
+ continue
|
|
+ flags, codec, name = match.groups()
|
|
+
|
|
+ if flags[0] == 'D':
|
|
+ decoders.add(codec)
|
|
+
|
|
+ if flags[1] == 'E':
|
|
+ encoders.add(codec)
|
|
+
|
|
+ return (decoders, encoders)
|
|
+
|
|
+
|
|
+def get_supported_decoders():
|
|
+ return get_supported_codecs()[0]
|
|
+
|
|
+
|
|
+def get_supported_encoders():
|
|
+ return get_supported_codecs()[1]
|
|
diff --git a/test/test.py b/test/test.py
|
|
index 415f14c..bc5d0c7 100644
|
|
--- a/test/test.py
|
|
+++ b/test/test.py
|
|
@@ -18,6 +18,8 @@ from pydub.utils import (
|
|
make_chunks,
|
|
mediainfo,
|
|
get_encoder_name,
|
|
+ get_supported_decoders,
|
|
+ get_supported_encoders,
|
|
)
|
|
from pydub.exceptions import (
|
|
InvalidTag,
|
|
@@ -670,6 +672,8 @@ class AudioSegmentTests(unittest.TestCase):
|
|
if sys.platform == 'win32':
|
|
os.remove(tmp_mp3_file.name)
|
|
|
|
+ @unittest.skipUnless('aac' in get_supported_decoders(),
|
|
+ "Unsupported codecs")
|
|
def test_formats(self):
|
|
seg_m4a = AudioSegment.from_file(
|
|
os.path.join(data_dir, 'format_test.m4a'), "m4a")
|
|
@@ -688,6 +692,8 @@ class AudioSegmentTests(unittest.TestCase):
|
|
wav = AudioSegment.from_wav(wav_file)
|
|
self.assertEqual(wav.duration_seconds, self.seg1.duration_seconds)
|
|
|
|
+ @unittest.skipUnless('aac' in get_supported_decoders(),
|
|
+ "Unsupported codecs")
|
|
def test_autodetect_format(self):
|
|
aac_path = os.path.join(data_dir, 'wrong_extension.aac')
|
|
fn = partial(AudioSegment.from_file, aac_path, "aac")
|
|
@@ -720,21 +726,29 @@ class AudioSegmentTests(unittest.TestCase):
|
|
AudioSegment.from_file(self.mp3_file_path).export(tmp_webm_file,
|
|
format="webm")
|
|
|
|
+ @unittest.skipUnless('aac' in get_supported_decoders(),
|
|
+ "Unsupported codecs")
|
|
def test_export_mp4_as_ogg(self):
|
|
with NamedTemporaryFile('w+b', suffix='.ogg') as tmp_ogg_file:
|
|
AudioSegment.from_file(self.mp4_file_path).export(tmp_ogg_file,
|
|
format="ogg")
|
|
|
|
+ @unittest.skipUnless('aac' in get_supported_decoders(),
|
|
+ "Unsupported codecs")
|
|
def test_export_mp4_as_mp3(self):
|
|
with NamedTemporaryFile('w+b', suffix='.mp3') as tmp_mp3_file:
|
|
AudioSegment.from_file(self.mp4_file_path).export(tmp_mp3_file,
|
|
format="mp3")
|
|
|
|
+ @unittest.skipUnless('aac' in get_supported_decoders(),
|
|
+ "Unsupported codecs")
|
|
def test_export_mp4_as_wav(self):
|
|
with NamedTemporaryFile('w+b', suffix='.wav') as tmp_wav_file:
|
|
AudioSegment.from_file(self.mp4_file_path).export(tmp_wav_file,
|
|
format="mp3")
|
|
|
|
+ @unittest.skipUnless('aac' in get_supported_decoders(),
|
|
+ "Unsupported codecs")
|
|
def test_export_mp4_as_mp3_with_tags(self):
|
|
with NamedTemporaryFile('w+b', suffix='.mp3') as tmp_mp3_file:
|
|
tags_dict = {
|
|
@@ -746,6 +760,8 @@ class AudioSegmentTests(unittest.TestCase):
|
|
format="mp3",
|
|
tags=tags_dict)
|
|
|
|
+ @unittest.skipUnless('aac' in get_supported_decoders(),
|
|
+ "Unsupported codecs")
|
|
def test_export_mp4_as_mp3_with_tags_raises_exception_when_tags_are_not_a_dictionary(self):
|
|
with NamedTemporaryFile('w+b', suffix='.mp3') as tmp_mp3_file:
|
|
json = '{"title": "The Title You Want", "album": "Name of the Album", "artist": "Artist\'s name"}'
|
|
@@ -754,6 +770,8 @@ class AudioSegmentTests(unittest.TestCase):
|
|
format="mp3", tags=json)
|
|
self.assertRaises(InvalidTag, func)
|
|
|
|
+ @unittest.skipUnless('aac' in get_supported_decoders(),
|
|
+ "Unsupported codecs")
|
|
def test_export_mp4_as_mp3_with_tags_raises_exception_when_id3version_is_wrong(self):
|
|
tags = {'artist': 'Artist', 'title': 'Title'}
|
|
with NamedTemporaryFile('w+b', suffix='.mp3') as tmp_mp3_file:
|
|
@@ -766,6 +784,8 @@ class AudioSegmentTests(unittest.TestCase):
|
|
)
|
|
self.assertRaises(InvalidID3TagVersion, func)
|
|
|
|
+ @unittest.skipUnless('aac' in get_supported_decoders(),
|
|
+ "Unsupported codecs")
|
|
def test_export_mp3_with_tags(self):
|
|
tags = {'artist': 'Mozart', 'title': 'The Magic Flute'}
|
|
|
|
@@ -883,6 +903,8 @@ class AudioSegmentTests(unittest.TestCase):
|
|
# average volume should be reduced
|
|
self.assertTrue(compressed.rms < self.seg1.rms)
|
|
|
|
+ @unittest.skipUnless('aac' in get_supported_decoders(),
|
|
+ "Unsupported codecs")
|
|
def test_exporting_to_ogg_uses_default_codec_when_codec_param_is_none(self):
|
|
delete = sys.platform != 'win32'
|
|
|
|
--
|
|
2.20.1
|
|
|