1
0
mirror of https://codeberg.org/polarisfm/youtube-dl synced 2024-11-26 02:14:32 +01:00

[ffmpeg] Support splitting target based on extracted chapters (#24858)

This introduces a new FFmpegPostProcessor, which looks for "chapters"
extracted by IEs. For each identified chapter, it extracts a single
track from the source file, using ffmpeg's -ss / -t arguments.
This commit is contained in:
Wattux 2020-04-19 14:08:09 +02:00 committed by Watte
parent 07af16b92e
commit dcab7389ac
4 changed files with 56 additions and 0 deletions

View File

@ -293,6 +293,8 @@ def _real_main(argv=None):
}) })
if not already_have_thumbnail: if not already_have_thumbnail:
opts.writethumbnail = True opts.writethumbnail = True
if opts.split_tracks:
postprocessors.append({'key': 'FFmpegSplitByTracks'})
# XAttrMetadataPP should be run after post-processors that may change file # XAttrMetadataPP should be run after post-processors that may change file
# contents # contents
if opts.xattrs: if opts.xattrs:

View File

@ -525,6 +525,11 @@ def parseOpts(overrideArguments=None):
'--external-downloader-args', '--external-downloader-args',
dest='external_downloader_args', metavar='ARGS', dest='external_downloader_args', metavar='ARGS',
help='Give these arguments to the external downloader') help='Give these arguments to the external downloader')
downloader.add_option(
'--split-tracks',
dest='split_tracks', action='store_true', default=False,
help="Split tracks based on chapters information"
)
workarounds = optparse.OptionGroup(parser, 'Workarounds') workarounds = optparse.OptionGroup(parser, 'Workarounds')
workarounds.add_option( workarounds.add_option(

View File

@ -12,6 +12,7 @@ from .ffmpeg import (
FFmpegMetadataPP, FFmpegMetadataPP,
FFmpegVideoConvertorPP, FFmpegVideoConvertorPP,
FFmpegSubtitlesConvertorPP, FFmpegSubtitlesConvertorPP,
FFmpegSplitByTracksPP,
) )
from .xattrpp import XAttrMetadataPP from .xattrpp import XAttrMetadataPP
from .execafterdownload import ExecAfterDownloadPP from .execafterdownload import ExecAfterDownloadPP
@ -27,6 +28,7 @@ __all__ = [
'ExecAfterDownloadPP', 'ExecAfterDownloadPP',
'FFmpegEmbedSubtitlePP', 'FFmpegEmbedSubtitlePP',
'FFmpegExtractAudioPP', 'FFmpegExtractAudioPP',
'FFmpegSplitByTracksPP',
'FFmpegFixupM3u8PP', 'FFmpegFixupM3u8PP',
'FFmpegFixupM4aPP', 'FFmpegFixupM4aPP',
'FFmpegFixupStretchedPP', 'FFmpegFixupStretchedPP',

View File

@ -1,6 +1,7 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import io import io
import logging
import os import os
import subprocess import subprocess
import time import time
@ -655,3 +656,49 @@ class FFmpegSubtitlesConvertorPP(FFmpegPostProcessor):
} }
return sub_filenames, info return sub_filenames, info
class FFmpegSplitByTracksPP(FFmpegPostProcessor):
log = logging.getLogger(__name__)
def _ffmpeg_time_string(self, seconds):
t_minutes, t_seconds = divmod(seconds, 60)
t_hours, t_minutes = divmod(t_minutes, 60)
t_string = '{hrs:02}:{min:02}:{sec:02}'.format(hrs=t_hours, min=t_minutes, sec=t_seconds)
return t_string
def _build_track_name(self, chapter, information):
track_title = chapter.get("title", "")
track_title = encodeFilename(track_title)
track_title = track_title.replace("/", "_")
prefix, sep, ext = information['filepath'].rpartition('.')
track_name = "%s - %s%s%s" % (prefix, track_title, sep, ext)
return track_name
def _extract_track_from_chapter(self, chapter, information):
start = int(chapter['start_time'])
end = int(chapter['end_time'])
duration = end - start
start = self._ffmpeg_time_string(start)
duration = self._ffmpeg_time_string(duration)
destination = self._build_track_name(chapter, information)
self.run_ffmpeg(information['filepath'], destination, ['-c', 'copy', '-ss', start, '-t', duration])
def run(self, information):
chapters = information.get('chapters', [])
if not isinstance(chapters, list) or len(chapters) == 0:
self.log.warning('[ffmpeg] There are no tracks to extract')
return [], information
for idx, chapter in enumerate(chapters):
try:
self._extract_track_from_chapter(chapter, information)
except Exception as e:
self.log.error('Splitting track failed: ' + repr(e))
return [], information