From 8ec0a44e77e071d67187d4b42f44cd4ac2c89b2b Mon Sep 17 00:00:00 2001 From: Javinator9889 Date: Tue, 8 Oct 2019 11:17:49 +0200 Subject: [PATCH] Audio conversion preserving metadata --- YouTubeMDBot/audio/__init__.py | 2 + YouTubeMDBot/audio/ffmpeg.py | 48 +++++++++++++++++++ YouTubeMDBot/downloader/youtube_downloader.py | 7 --- YouTubeMDBot/tests/converter.py | 37 ++++++++++++++ 4 files changed, 87 insertions(+), 7 deletions(-) create mode 100644 YouTubeMDBot/tests/converter.py diff --git a/YouTubeMDBot/audio/__init__.py b/YouTubeMDBot/audio/__init__.py index c6ce402..49eab31 100755 --- a/YouTubeMDBot/audio/__init__.py +++ b/YouTubeMDBot/audio/__init__.py @@ -14,5 +14,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . from ..audio.ffmpeg import FFmpegOpener +from ..audio.ffmpeg import FFmpegOGG +from ..audio.ffmpeg import FFmpegMP3 from ..audio.ffmpeg import ffmpeg_available from ..audio.fpcalc import FPCalc diff --git a/YouTubeMDBot/audio/ffmpeg.py b/YouTubeMDBot/audio/ffmpeg.py index b04f5d7..0bf9930 100755 --- a/YouTubeMDBot/audio/ffmpeg.py +++ b/YouTubeMDBot/audio/ffmpeg.py @@ -47,3 +47,51 @@ def get_output(self) -> bytes: def get_extra(self) -> bytes: return self.__err + + +class FFmpegExporter: + def __init__(self, data: BytesIO): + self._data = data + self.__command = ["ffmpeg", "-i", "-", "-vn", "-map_metadata", "0", + "-movflags", "use_metadata_tags"] + self.__out = None + self.__err = None + + def _call_ffmpeg(self): + self._data.seek(0) + proc = Popen(self.__command, stdout=PIPE, stderr=PIPE, stdin=PIPE) + self.__out, self.__err = proc.communicate(self._data.read()) + + def _get_command(self) -> list: + return self.__command + + def convert(self): + raise NotImplementedError + + def get_output(self) -> bytes: + return self.__out + + def get_err(self) -> bytes: + return self.__err + + +class FFmpegMP3(FFmpegExporter): + def convert(self): + command = super()._get_command() + command.append("-acodec") + command.append("libmp3lame") + command.append("-f") + command.append("mp3") + command.append("-") + self._call_ffmpeg() + + +class FFmpegOGG(FFmpegExporter): + def convert(self): + command = super()._get_command() + command.append("-c:a") + command.append("libvorbis") + command.append("-f") + command.append("ogg") + command.append("-") + self._call_ffmpeg() diff --git a/YouTubeMDBot/downloader/youtube_downloader.py b/YouTubeMDBot/downloader/youtube_downloader.py index dfbb934..1692b34 100755 --- a/YouTubeMDBot/downloader/youtube_downloader.py +++ b/YouTubeMDBot/downloader/youtube_downloader.py @@ -35,13 +35,6 @@ def download(self, ffmpeg: bool = False) -> Tuple[BytesIO, bytes]: stdout, stderr = proc.communicate() retcode = proc.returncode if retcode == 0: - # if ffmpeg: - # opener = FFmpegOpener(stdout) - # opener.open() - # stdout = opener.get_output() - # err = opener.get_extra() - # if err: - # print(err.decode("utf-8")) return BytesIO(stdout), stdout else: raise RuntimeError("youtube-dl downloader exception - more info: " + diff --git a/YouTubeMDBot/tests/converter.py b/YouTubeMDBot/tests/converter.py new file mode 100644 index 0000000..9d7db7f --- /dev/null +++ b/YouTubeMDBot/tests/converter.py @@ -0,0 +1,37 @@ +import unittest +import mutagen + +from typing import Tuple +from io import BytesIO + +from YouTubeMDBot.tests.tagger import TaggerTest +from YouTubeMDBot.downloader import YouTubeDownloader +from YouTubeMDBot.audio import FFmpegMP3 +from YouTubeMDBot.audio import FFmpegOGG + + +class MyTestCase(TaggerTest): + def find_metadata(self, downloader: YouTubeDownloader) -> Tuple[BytesIO, bytes]: + io, data = super().find_metadata(downloader) + io.seek(0) + mp3 = FFmpegMP3(data=io) + ogg = FFmpegOGG(data=io) + + mp3.convert() + io.seek(0) + ogg.convert() + + mp3_container = BytesIO(mp3.get_output()) + ogg_container = BytesIO(ogg.get_output()) + + print(mp3.get_err().decode("utf-8")) + print(ogg.get_err().decode("utf-8")) + + print(mutagen.File(mp3_container).pprint()) + print(mutagen.File(ogg_container).pprint()) + + return io, data + + +if __name__ == '__main__': + unittest.main()