Add a post processor for joining video parts
This commit is contained in:
parent
1e705ca327
commit
fbbc7df126
@ -2,6 +2,7 @@ import os
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
import io
|
||||
|
||||
|
||||
from .utils import (
|
||||
@ -78,15 +79,15 @@ class FFmpegPostProcessor(PostProcessor):
|
||||
programs = ['avprobe', 'avconv', 'ffmpeg', 'ffprobe']
|
||||
return dict((program, executable(program)) for program in programs)
|
||||
|
||||
def run_ffmpeg_multiple_files(self, input_paths, out_path, opts):
|
||||
def run_ffmpeg_multiple_files(self, input_paths, out_path, opts, input_opts=[]):
|
||||
if not self._exes['ffmpeg'] and not self._exes['avconv']:
|
||||
raise FFmpegPostProcessorError(u'ffmpeg or avconv not found. Please install one.')
|
||||
|
||||
files_cmd = []
|
||||
for path in input_paths:
|
||||
files_cmd.extend(['-i', encodeFilename(path)])
|
||||
cmd = ([self._exes['avconv'] or self._exes['ffmpeg'], '-y'] + files_cmd
|
||||
+ opts +
|
||||
cmd = ([self._exes['avconv'] or self._exes['ffmpeg'], '-y'] +
|
||||
input_opts + files_cmd + opts +
|
||||
[encodeFilename(self._ffmpeg_filename_argument(out_path))])
|
||||
|
||||
if self._downloader.params.get('verbose', False):
|
||||
@ -98,8 +99,8 @@ class FFmpegPostProcessor(PostProcessor):
|
||||
msg = stderr.strip().split('\n')[-1]
|
||||
raise FFmpegPostProcessorError(msg)
|
||||
|
||||
def run_ffmpeg(self, path, out_path, opts):
|
||||
self.run_ffmpeg_multiple_files([path], out_path, opts)
|
||||
def run_ffmpeg(self, path, out_path, opts, input_opts=[]):
|
||||
self.run_ffmpeg_multiple_files([path], out_path, opts, input_opts)
|
||||
|
||||
def _ffmpeg_filename_argument(self, fn):
|
||||
# ffmpeg broke --, see https://ffmpeg.org/trac/ffmpeg/ticket/2127 for details
|
||||
@ -509,3 +510,18 @@ class FFmpegMetadataPP(FFmpegPostProcessor):
|
||||
os.remove(encodeFilename(filename))
|
||||
os.rename(encodeFilename(temp_filename), encodeFilename(filename))
|
||||
return True, info
|
||||
|
||||
|
||||
class FFmpegJoinVideos(FFmpegPostProcessor):
|
||||
def join(self, final_video, videos):
|
||||
files_file = u'%s.videos' % final_video
|
||||
with io.open(encodeFilename(files_file), 'w', encoding='utf-8') as f:
|
||||
for video in videos:
|
||||
f.write(u'file \'%s\'\n' % video)
|
||||
self._downloader.to_screen(u'[ffmpeg] Joining video parts, destination: %s' % final_video)
|
||||
try:
|
||||
self.run_ffmpeg(files_file, final_video, ['-c', 'copy'], ['-f', 'concat'])
|
||||
except FFmpegPostProcessorError:
|
||||
return False
|
||||
os.remove(encodeFilename(files_file))
|
||||
return True
|
||||
|
@ -52,6 +52,7 @@ from .utils import (
|
||||
from .extractor import get_info_extractor, gen_extractors
|
||||
from .FileDownloader import FileDownloader
|
||||
from .version import __version__
|
||||
from .PostProcessor import FFmpegJoinVideos
|
||||
|
||||
|
||||
class YoutubeDL(object):
|
||||
@ -790,6 +791,16 @@ class YoutubeDL(object):
|
||||
parts_files.append(part_filename)
|
||||
parts_success.append(self.fd._do_download(part_filename, part_info))
|
||||
success = all(parts_success)
|
||||
if success:
|
||||
video_joiner = FFmpegJoinVideos(self)
|
||||
join_success = video_joiner.join(filename, parts_files)
|
||||
if not join_success:
|
||||
self.report_error(u'Could not join the video parts')
|
||||
else:
|
||||
self.to_screen(u'[info] Removing video parts')
|
||||
for part_file in parts_files:
|
||||
os.remove(encodeFilename(part_file))
|
||||
success = join_success
|
||||
except (compat_urllib_error.URLError, compat_http_client.HTTPException, socket.error) as err:
|
||||
self.report_error(u'unable to download video data: %s' % str(err))
|
||||
return
|
||||
|
Loading…
x
Reference in New Issue
Block a user