aboutsummaryrefslogtreecommitdiff
path: root/youtube_dlc/postprocessor
diff options
context:
space:
mode:
Diffstat (limited to 'youtube_dlc/postprocessor')
-rw-r--r--youtube_dlc/postprocessor/__init__.py2
-rw-r--r--youtube_dlc/postprocessor/embedthumbnail.py15
-rw-r--r--youtube_dlc/postprocessor/ffmpeg.py11
-rw-r--r--youtube_dlc/postprocessor/sponskrub.py86
4 files changed, 102 insertions, 12 deletions
diff --git a/youtube_dlc/postprocessor/__init__.py b/youtube_dlc/postprocessor/__init__.py
index 2c4702823..e160909a7 100644
--- a/youtube_dlc/postprocessor/__init__.py
+++ b/youtube_dlc/postprocessor/__init__.py
@@ -17,6 +17,7 @@ from .ffmpeg import (
from .xattrpp import XAttrMetadataPP
from .execafterdownload import ExecAfterDownloadPP
from .metadatafromtitle import MetadataFromTitlePP
+from .sponskrub import SponSkrubPP
def get_postprocessor(key):
@@ -38,5 +39,6 @@ __all__ = [
'FFmpegVideoConvertorPP',
'FFmpegVideoRemuxerPP',
'MetadataFromTitlePP',
+ 'SponSkrubPP',
'XAttrMetadataPP',
]
diff --git a/youtube_dlc/postprocessor/embedthumbnail.py b/youtube_dlc/postprocessor/embedthumbnail.py
index 4a0d02fc4..94e3eca98 100644
--- a/youtube_dlc/postprocessor/embedthumbnail.py
+++ b/youtube_dlc/postprocessor/embedthumbnail.py
@@ -76,8 +76,8 @@ class EmbedThumbnailPP(FFmpegPostProcessor):
if info['ext'] == 'mp3':
options = [
- '-c', 'copy', '-map', '0', '-map', '1',
- '-metadata:s:v', 'title="Album cover"', '-metadata:s:v', 'comment="Cover (Front)"']
+ '-c', 'copy', '-map', '0:0', '-map', '1:0', '-id3v2_version', '3',
+ '-metadata:s:v', 'title="Album cover"', '-metadata:s:v', 'comment="Cover (front)"']
self._downloader.to_screen('[ffmpeg] Adding thumbnail to "%s"' % filename)
@@ -89,12 +89,15 @@ class EmbedThumbnailPP(FFmpegPostProcessor):
os.rename(encodeFilename(temp_filename), encodeFilename(filename))
elif info['ext'] == 'mkv':
- os.rename(encodeFilename(thumbnail_filename), encodeFilename('cover.jpg'))
old_thumbnail_filename = thumbnail_filename
- thumbnail_filename = 'cover.jpg'
+ thumbnail_filename = os.path.join(os.path.dirname(old_thumbnail_filename), 'cover.jpg')
+ if os.path.exists(thumbnail_filename):
+ os.remove(encodeFilename(thumbnail_filename))
+ os.rename(encodeFilename(old_thumbnail_filename), encodeFilename(thumbnail_filename))
options = [
- '-c', 'copy', '-attach', thumbnail_filename, '-metadata:s:t', 'mimetype=image/jpeg']
+ '-c', 'copy', '-map', '0',
+ '-attach', thumbnail_filename, '-metadata:s:t', 'mimetype=image/jpeg']
self._downloader.to_screen('[ffmpeg] Adding thumbnail to "%s"' % filename)
@@ -140,6 +143,6 @@ class EmbedThumbnailPP(FFmpegPostProcessor):
os.remove(encodeFilename(filename))
os.rename(encodeFilename(temp_filename), encodeFilename(filename))
else:
- raise EmbedThumbnailPPError('Only mp3 and m4a/mp4 are supported for thumbnail embedding for now.')
+ raise EmbedThumbnailPPError('Only mp3, mkv, m4a and mp4 are supported for thumbnail embedding for now.')
return [], info
diff --git a/youtube_dlc/postprocessor/ffmpeg.py b/youtube_dlc/postprocessor/ffmpeg.py
index c38db3143..c7071d73d 100644
--- a/youtube_dlc/postprocessor/ffmpeg.py
+++ b/youtube_dlc/postprocessor/ffmpeg.py
@@ -359,7 +359,7 @@ class FFmpegVideoRemuxerPP(FFmpegPostProcessor):
if information['ext'] == self._preferedformat:
self._downloader.to_screen('[ffmpeg] Not remuxing video file %s - already is in target format %s' % (path, self._preferedformat))
return [], information
- options = ['-c', 'copy']
+ options = ['-c', 'copy', '-map', '0']
prefix, sep, ext = path.rpartition('.')
outpath = prefix + sep + self._preferedformat
self._downloader.to_screen('[' + 'ffmpeg' + '] Remuxing video from %s to %s, Destination: ' % (information['ext'], self._preferedformat) + outpath)
@@ -428,8 +428,7 @@ class FFmpegEmbedSubtitlePP(FFmpegPostProcessor):
input_files = [filename] + sub_filenames
opts = [
- '-map', '0',
- '-c', 'copy',
+ '-c', 'copy', '-map', '0',
# Don't copy the existing subtitles, we may be running the
# postprocessor a second time
'-map', '-0:s',
@@ -579,7 +578,7 @@ class FFmpegFixupStretchedPP(FFmpegPostProcessor):
filename = info['filepath']
temp_filename = prepend_extension(filename, 'temp')
- options = ['-c', 'copy', '-aspect', '%f' % stretched_ratio]
+ options = ['-c', 'copy', '-map', '0', '-aspect', '%f' % stretched_ratio]
self._downloader.to_screen('[ffmpeg] Fixing aspect ratio in "%s"' % filename)
self.run_ffmpeg(filename, temp_filename, options)
@@ -597,7 +596,7 @@ class FFmpegFixupM4aPP(FFmpegPostProcessor):
filename = info['filepath']
temp_filename = prepend_extension(filename, 'temp')
- options = ['-c', 'copy', '-f', 'mp4']
+ options = ['-c', 'copy', '-map', '0', '-f', 'mp4']
self._downloader.to_screen('[ffmpeg] Correcting container in "%s"' % filename)
self.run_ffmpeg(filename, temp_filename, options)
@@ -613,7 +612,7 @@ class FFmpegFixupM3u8PP(FFmpegPostProcessor):
if self.get_audio_codec(filename) == 'aac':
temp_filename = prepend_extension(filename, 'temp')
- options = ['-c', 'copy', '-f', 'mp4', '-bsf:a', 'aac_adtstoasc']
+ options = ['-c', 'copy', '-map', '0', '-f', 'mp4', '-bsf:a', 'aac_adtstoasc']
self._downloader.to_screen('[ffmpeg] Fixing malformed AAC bitstream in "%s"' % filename)
self.run_ffmpeg(filename, temp_filename, options)
diff --git a/youtube_dlc/postprocessor/sponskrub.py b/youtube_dlc/postprocessor/sponskrub.py
new file mode 100644
index 000000000..8ef612050
--- /dev/null
+++ b/youtube_dlc/postprocessor/sponskrub.py
@@ -0,0 +1,86 @@
+from __future__ import unicode_literals
+import os
+import subprocess
+
+from .common import PostProcessor
+from ..compat import compat_shlex_split
+from ..utils import (
+ check_executable,
+ encodeArgument,
+ shell_quote,
+ PostProcessingError,
+)
+
+
+class SponSkrubPP(PostProcessor):
+ _temp_ext = 'spons'
+ _def_args = []
+ _exe_name = 'sponskrub'
+
+ def __init__(self, downloader, path='', args=None, ignoreerror=False, cut=False, force=False):
+ PostProcessor.__init__(self, downloader)
+ self.force = force
+ self.cutout = cut
+ self.args = ['-chapter'] if not cut else []
+ self.args += self._def_args if args is None else compat_shlex_split(args)
+ self.path = self.get_exe(path)
+
+ if not ignoreerror and self.path is None:
+ if path:
+ raise PostProcessingError('sponskrub not found in "%s"' % path)
+ else:
+ raise PostProcessingError('sponskrub not found. Please install or provide the path using --sponskrub-path.')
+
+ def get_exe(self, path=''):
+ if not path or not check_executable(path, ['-h']):
+ path = os.path.join(path, self._exe_name)
+ if not check_executable(path, ['-h']):
+ return None
+ return path
+
+ def run(self, information):
+ if self.path is None:
+ return [], information
+
+ if information['extractor_key'].lower() != 'youtube':
+ self._downloader.to_screen('[sponskrub] Skipping sponskrub since it is not a YouTube video')
+ return [], information
+ if self.cutout and not self.force and not information.get('__real_download', False):
+ self._downloader.to_screen(
+ '[sponskrub] Skipping sponskrub since the video was already downloaded. '
+ 'Use --sponskrub-force to run sponskrub anyway')
+ return [], information
+
+ self._downloader.to_screen('[sponskrub] Trying to %s sponsor sections' % ('remove' if self.cutout else 'mark'))
+ if self.cutout:
+ self._downloader.to_screen('WARNING: Cutting out sponsor segments will cause the subtitles to go out of sync.')
+ if not information.get('__real_download', False):
+ self._downloader.to_screen('WARNING: If sponskrub is run multiple times, unintended parts of the video could be cut out.')
+
+ filename = information['filepath']
+ temp_filename = filename + '.' + self._temp_ext + os.path.splitext(filename)[1]
+ if os.path.exists(temp_filename):
+ os.remove(temp_filename)
+
+ cmd = [self.path]
+ if self.args:
+ cmd += self.args
+ cmd += ['--', information['id'], filename, temp_filename]
+ cmd = [encodeArgument(i) for i in cmd]
+
+ if self._downloader.params.get('verbose', False):
+ self._downloader.to_screen('[debug] sponskrub command line: %s' % shell_quote(cmd))
+ p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
+ stdout, stderr = p.communicate()
+
+ if p.returncode == 0:
+ os.remove(filename)
+ os.rename(temp_filename, filename)
+ self._downloader.to_screen('[sponskrub] Sponsor sections have been %s' % ('removed' if self.cutout else 'marked'))
+ elif p.returncode != 3: # error code 3 means there was no info about the video
+ stderr = stderr.decode('utf-8', 'replace')
+ msg = stderr.strip().split('\n')[-1]
+ raise PostProcessingError(msg if msg else 'sponskrub failed with error code %s!' % p.returncode)
+ else:
+ self._downloader.to_screen('[sponskrub] No segments in the SponsorBlock database')
+ return [], information