14
0
forked from pool/python-pydub

Accepting request 878359 from devel:languages:python

OBS-URL: https://build.opensuse.org/request/show/878359
OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/python-pydub?expand=0&rev=7
This commit is contained in:
2021-03-11 19:11:53 +00:00
committed by Git OBS Bridge
5 changed files with 52 additions and 205 deletions

View File

@@ -1,195 +0,0 @@
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

View File

@@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:a5ee51e6bac1e3f64eefd5176aac3299a75e4deec9ad6fef87c3d936f4a034dc
size 27180893

3
pydub-0.25.1.tar.gz Normal file
View File

@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:94f423c9acc9f361203e82a204420bb8fb85731d0586ebd2c1509fbeadeabad6
size 27555582

View File

@@ -1,3 +1,49 @@
-------------------------------------------------------------------
Wed Mar 10 20:05:05 UTC 2021 - Ben Greiner <code@bnavigator.de>
- Update to 0.25.1
* Fix crashing bug in new scipy-powered EQ effects
- Release 0.25.0
* Don't show a runtime warning about the optional ffplay
dependency being missing until someone trys to use it
* Documentation improvements
* Python 3.9 support
* Improved efficiency of loading wave files with pydub.
AudioSegment.from_file()
* Ensure pydub.AudioSegment().export() always retuns files with
a seek position at the beginning of the file
* Added more EQ effects to pydub.scipy_effects (requires scipy
to be installed)
* Fix a packaging bug where the LICENSE file was not included in
the source distribution
* Add a way to instantiate a pydub.AudioSegment() with a portion
of an audio file via pydub.AudioSegment().from_file()
- Release 0.24.1
* Fix bug where ffmpeg errors in Python 3 are illegible
* Fix bug where split_on_silence fails when there are one or
fewer nonsilent segments
* Fix bug in fallback audioop implementation
- Release 0.24.0
* Fix inconsistent handling of 8-bit audio
* Fix bug where certain files will fail to parse
* Fix bug where pyaudio stream is not closed on error
* Allow codecs and parameters in wav and raw export
* Fix bug in pydub.AudioSegment.from_file where supplied codec
is ignored
* Allow pydub.silence.split_on_silence to take a boolean for
keep_silence
* Fix bug where pydub.silence.split_on_silence sometimes adds
non-silence from adjacent segments
* Fix bug where pydub.AudioSegment.extract_wav_headers fails on
empty wav files
* Add new function pydub.silence.detect_leading_silence
* Support conversion between an arbitrary number of channels and
mono in pydub.AudioSegment.set_channels
* Fix several issues related to reading from filelike objects
- Drop 0001-Skip-tests-that-use-unavailable-codecs.patch merged
upstream
- Reinstate python36 build. SciPy is optional
-------------------------------------------------------------------
Sat Feb 13 10:14:16 UTC 2021 - Dirk Müller <dmueller@suse.com>

View File

@@ -17,22 +17,19 @@
%{?!python_module:%define python_module() python-%{**} python3-%{**}}
%global skip_python36 1
Name: python-pydub
Version: 0.23.1
Version: 0.25.1
Release: 0
Summary: Audio manipulation with Python
License: MIT
Group: Development/Languages/Python
URL: https://github.com/jiaaro/pydub
Source: https://github.com/jiaaro/pydub/archive/v%{version}.tar.gz#/pydub-%{version}.tar.gz
# PATCH-FIX-UPSTREAM
Patch0: 0001-Skip-tests-that-use-unavailable-codecs.patch
BuildRequires: %{python_module scipy}
BuildRequires: %{python_module setuptools}
BuildRequires: fdupes
BuildRequires: ffmpeg
BuildRequires: python-rpm-macros
BuildRequires: %{python_module scipy if (%python-base without python36-base)}
Recommends: python-scipy
Recommends: python-simpleaudio
Requires: ffmpeg
@@ -45,7 +42,6 @@ A Python module to manipulate audio with a high level interface.
%prep
%setup -q -n pydub-%{version}
%patch0 -p1
%build
%python_build
@@ -55,7 +51,7 @@ A Python module to manipulate audio with a high level interface.
%python_expand %fdupes %{buildroot}%{$python_sitelib}
%check
%python_expand PYTHONPATH=%{buildroot}%{$python_sitelib} $python test/test.py
%pyunittest -v test.test
%files %{python_files}
%license LICENSE