added flag to merge videos from a playlist into one continuous file
This commit is contained in:
parent
b8b01bb92a
commit
2cd5408951
@ -59,7 +59,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__
|
||||
|
||||
|
||||
@ -645,6 +645,32 @@ class YoutubeDL(object):
|
||||
extra_info=extra)
|
||||
playlist_results.append(entry_result)
|
||||
ie_result['entries'] = playlist_results
|
||||
|
||||
if download and not(self.params.get('simulate', False)) and \
|
||||
self.params.get('concat', False):
|
||||
downloaded = []
|
||||
concat = FFmpegConcatPP(self)
|
||||
if not concat._get_executable():
|
||||
postprocessors = []
|
||||
self.report_warning('You have requested multiple '
|
||||
'formats but ffmpeg or avconv are not installed.'
|
||||
' The formats won\'t be merged')
|
||||
else:
|
||||
postprocessors = [concat]
|
||||
for f in ie_result['entries']:
|
||||
new_info = dict(ie_result)
|
||||
new_info.update(f)
|
||||
if 'ext' in new_info: ie_result['ext'] = new_info['ext']
|
||||
if 'id' in new_info: ie_result['id'] = new_info['id']
|
||||
fname = self.prepare_filename(new_info)
|
||||
downloaded.append(fname)
|
||||
|
||||
filename = self.prepare_filename(ie_result)
|
||||
|
||||
ie_result['__postprocessors'] = postprocessors
|
||||
ie_result['__files_to_merge'] = downloaded
|
||||
self.post_process(filename, ie_result)
|
||||
|
||||
return ie_result
|
||||
elif result_type == 'compat_list':
|
||||
def _fixup(r):
|
||||
|
@ -500,6 +500,8 @@ def parseOpts(overrideArguments=None):
|
||||
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('--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('--concat', action='store_true', dest='concat',
|
||||
help='Attempt to concatenate multiple videos into one file')
|
||||
postproc.add_option('-k', '--keep-video', action='store_true', dest='keepvideo', default=False,
|
||||
help='keeps the video file on disk after the post-processing; the video is erased by default')
|
||||
postproc.add_option('--no-post-overwrites', action='store_true', dest='nopostoverwrites', default=False,
|
||||
@ -518,6 +520,7 @@ def parseOpts(overrideArguments=None):
|
||||
help='Prefer ffmpeg over avconv for running the postprocessors')
|
||||
|
||||
|
||||
|
||||
parser.add_option_group(general)
|
||||
parser.add_option_group(selection)
|
||||
parser.add_option_group(downloader)
|
||||
@ -791,6 +794,7 @@ def _real_main(argv=None):
|
||||
'bidi_workaround': opts.bidi_workaround,
|
||||
'debug_printtraffic': opts.debug_printtraffic,
|
||||
'prefer_ffmpeg': opts.prefer_ffmpeg,
|
||||
'concat': opts.concat,
|
||||
'include_ads': opts.include_ads,
|
||||
'default_search': opts.default_search,
|
||||
'youtube_include_dash_manifest': opts.youtube_include_dash_manifest,
|
||||
|
@ -1,6 +1,7 @@
|
||||
|
||||
from .atomicparsley import AtomicParsleyPP
|
||||
from .ffmpeg import (
|
||||
FFmpegConcatPP,
|
||||
FFmpegAudioFixPP,
|
||||
FFmpegMergerPP,
|
||||
FFmpegMetadataPP,
|
||||
@ -12,6 +13,7 @@ from .xattrpp import XAttrMetadataPP
|
||||
|
||||
__all__ = [
|
||||
'AtomicParsleyPP',
|
||||
'FFmpegConcatPP',
|
||||
'FFmpegAudioFixPP',
|
||||
'FFmpegMergerPP',
|
||||
'FFmpegMetadataPP',
|
||||
|
@ -487,6 +487,35 @@ class FFmpegMergerPP(FFmpegPostProcessor):
|
||||
self.run_ffmpeg_multiple_files(info['__files_to_merge'], filename, args)
|
||||
return True, info
|
||||
|
||||
class FFmpegConcatPP(FFmpegPostProcessor):
|
||||
def run(self, info):
|
||||
filename = info['filepath']
|
||||
args = ['-f', 'concat', '-i', '-', '-c', 'copy']
|
||||
self._downloader.to_screen(u'[ffmpeg] Concatenating files into "%s"' % filename)
|
||||
|
||||
if not self._get_executable():
|
||||
raise FFmpegPostProcessorError(u'ffmpeg or avconv not found. Please install one.')
|
||||
|
||||
cmd = ([self._get_executable(), '-y'] + args +
|
||||
[encodeFilename(self._ffmpeg_filename_argument(filename), True)])
|
||||
files = info['__files_to_merge']
|
||||
|
||||
if self._downloader.params.get('verbose', False):
|
||||
self._downloader.to_screen(u'[debug] ffmpeg command line: %s' % shell_quote(cmd))
|
||||
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
|
||||
files_cmd = u''
|
||||
for path in files:
|
||||
encoded_path = encodeFilename(path, True)
|
||||
files_cmd += u'file \'%s\'\n' % path
|
||||
stdout, stderr = p.communicate(input=files_cmd)
|
||||
if p.returncode != 0:
|
||||
stderr = stderr.decode('utf-8', 'replace')
|
||||
msg = stderr.strip().split('\n')[-1]
|
||||
raise FFmpegPostProcessorError(msg)
|
||||
|
||||
for path in files:
|
||||
os.remove(encodeFilename(path))
|
||||
|
||||
class FFmpegAudioFixPP(FFmpegPostProcessor):
|
||||
def run(self, info):
|
||||
|
Loading…
x
Reference in New Issue
Block a user