Implement initial concat support

It may not be pretty, but it friggin' works. Some initial testing with
The Daily Show, but I have no idea how it handles other sites.
This commit is contained in:
AGSPhoenix 2014-04-07 18:44:35 -04:00
parent d94fc760f7
commit 892328588a
3 changed files with 29 additions and 5 deletions

View File

@ -58,7 +58,7 @@ from .utils import (
)
from .extractor import get_info_extractor, gen_extractors
from .downloader import get_suitable_downloader
from .postprocessor import FFmpegMergerPP
from .postprocessor import FFmpegMergerPP, FFmpegConcatPP
from .version import __version__
@ -640,6 +640,18 @@ class YoutubeDL(object):
extra_info=extra)
playlist_results.append(entry_result)
ie_result['entries'] = playlist_results
#Run concat PP
if self.params['concat']:
pp = FFmpegConcatPP(self)
mergelist = []
for video in playlist_results:
mergelist.append(video['saved_filename'])
ie_result['__files_to_append'] = mergelist
pp.run(ie_result)
return ie_result
elif result_type == 'compat_list':
def _fixup(r):
@ -811,13 +823,16 @@ class YoutubeDL(object):
for format in formats_to_download:
new_info = dict(info_dict)
new_info.update(format)
self.process_info(new_info)
saved_filename = self.process_info(new_info)
#Maintain a list of saved files when processing playlists. Used by the concat PP.
info_dict['saved_filename'] = saved_filename
# We update the info dict with the best quality format (backwards compatibility)
info_dict.update(formats_to_download[-1])
return info_dict
def process_info(self, info_dict):
"""Process a single resolved IE result."""
"""Process a single resolved IE result. Returns the saved filename."""
assert info_dict.get('_type', 'video') == 'video'
@ -1019,6 +1034,7 @@ class YoutubeDL(object):
return
self.record_download_archive(info_dict)
return filename
def download(self, url_list):
"""Download a given list of URLs."""

View File

@ -97,6 +97,7 @@ from .postprocessor import (
FFmpegExtractAudioPP,
FFmpegEmbedSubtitlePP,
XAttrMetadataPP,
FFmpegConcatPP,
)
@ -495,6 +496,8 @@ def parseOpts(overrideArguments=None):
help='"best", "aac", "vorbis", "mp3", "m4a", "opus", or "wav"; best by default')
postproc.add_option('--audio-quality', metavar='QUALITY', dest='audioquality', default='5',
help='ffmpeg/avconv audio quality specification, insert a value between 0 (better) and 9 (worse) for VBR or a specific bitrate like 128K (default 5)')
postproc.add_option('--join', action='store_true', dest='concat', default=False,
help='when downloading a playlist of multiple videos, try to join them together end-to-end (EXPERIMENTAL)')
postproc.add_option('--recode-video', metavar='FORMAT', dest='recodevideo', default=None,
help='Encode the video to another format if necessary (currently supported: mp4|flv|ogg|webm)')
postproc.add_option('-k', '--keep-video', action='store_true', dest='keepvideo', default=False,
@ -790,6 +793,7 @@ def _real_main(argv=None):
'default_search': opts.default_search,
'youtube_include_dash_manifest': opts.youtube_include_dash_manifest,
'encoding': opts.encoding,
'concat': opts.concat,
}
with YoutubeDL(ydl_opts) as ydl:

View File

@ -488,13 +488,17 @@ class FFmpegMergerPP(FFmpegPostProcessor):
return True, info
class FFmpegConcatPP(FFmpegPostProcessor):
#Concat support requires that the IE return '_type' = 'playlist'
#Otherwise it silently fail
def run(self, info):
filename = info['filepath']
filename = info['title'] + u'.mp4' #What could possibly go wrong?
concatargs = ['-f', 'concat']
args = ['-c', 'copy']
self._downloader.to_screen(u'[ffmpeg] Appending files into "%s"' % filename)
#According to the ffmpeg docs this is literally how you're supposed to concat files.
#No method using solely the command line is listed. And I'm like "really?".
with open(u'youtube-dl_ffmpeg_append_list.txt', 'wb') as f:
for file in info['__files_to_merge']:
for file in info['__files_to_append']:
f.write("file '" + file + "'\n")
self.run_ffmpeg_multiple_files([u'youtube-dl_ffmpeg_append_list.txt'], filename, args, preopts=concatargs)
os.unlink('youtube-dl_ffmpeg_append_list.txt')