def test_video_remux(self): config = convert_config_from_ns({'video_codec': 'copy'}) with create_test_video(length=3, video_def=VideoDefinition(codec=VideoCodec.MPEG2)) as file, \ NamedTemporaryFile(suffix='.mkv') as output: convert_with_config(file.name, output.name, config, overwrite=True) metadata = extract_metadata(output.name) self.assertEqual(metadata.video_streams[0].codec, VideoCodec.MPEG2.ffmpeg_codec_name)
def test_scale_convert(self): config = ConvertConfig(scale=480) with create_test_video(length=4, video_def=VideoDefinition(resolution=Resolution.HIGH_DEF)) as file, \ NamedTemporaryFile(suffix='.mkv') as output: convert_with_config(file.name, output.name, config, overwrite=True) metadata = extract_metadata(output.name) self.assertEqual(metadata.resolution, Resolution.STANDARD_DEF)
def test_audio_remux(self): config = convert_config_from_ns({'audio_codec': 'copy'}) with create_test_video(length=3, audio_defs=[AudioDefition(codec=AudioCodec.AC3)]) as file, \ NamedTemporaryFile(suffix='.mkv') as output: convert_with_config(file.name, output.name, config, overwrite=True) metadata = extract_metadata(output.name) self.assertEqual(metadata.audio_streams[0].codec, AudioCodec.AC3.ffmpeg_codec_name)
def test_cut_convert(self): config = convert_config_from_ns({'start': 3.0, 'end': 6.0}) with create_test_video(length=10) as file, \ NamedTemporaryFile(suffix='.mkv') as output: convert_with_config(file.name, output.name, config, overwrite=True) metadata = extract_metadata(output.name) self.assertAlmostEqual(3.0, metadata.estimated_duration, delta=.03)
def test_mpeg2_convert(self): config = convert_config_from_ns( {'video_codec': VideoCodec.MPEG2.ffmpeg_encoder_name}) with create_test_video(length=3) as file, NamedTemporaryFile( suffix='.mkv') as output: convert_with_config(file.name, output.name, config, overwrite=True) metadata = extract_metadata(output.name) self.assertEqual(metadata.video_streams[0].codec.lower(), VideoCodec.MPEG2.ffmpeg_codec_name)
def test_defaults_convert(self): config = convert_config_from_ns({}) with create_test_video(length=3, video_def=VideoDefinition(resolution=Resolution.LOW_DEF, codec=VideoCodec.MPEG2), audio_defs=[AudioDefition(codec=AudioCodec.AC3)]) as file, \ NamedTemporaryFile(suffix='.mkv') as output: convert_with_config(file.name, output.name, config, overwrite=True) metadata = extract_metadata(output.name) self.assertEqual(metadata.resolution, Resolution.LOW_DEF) self.assertEqual(metadata.video_streams[0].codec, VideoCodec.H264.ffmpeg_codec_name) self.assertEqual(metadata.audio_streams[0].codec, AudioCodec.AAC.ffmpeg_codec_name)
def _validate_file(file): metadata = extract_metadata(file) if len(metadata.video_streams) != 1: raise Exception('Not exactly 1 video stream in {}'.format(file)) if not VideoCodec.H264.equals(metadata.video_streams[0].codec): raise Exception('File not H264: {}'.format(file)) non_aac_audio = [ a for a in metadata.audio_streams if not AudioCodec.AAC.equals(a.codec) ] if non_aac_audio: raise Exception('Not all audio streams are AAC: {}'.format(file))
def combine(video, srt, output, lang=None, overwrite=False, convert=False, crf=DEFAULT_CRF, preset=DEFAULT_PRESET, skip_eia_608=True): if not overwrite and check_exists(output): return -1 if srt.endswith('.ttml') or srt.endswith('.xml'): logger.debug('Converting ttml/xml to srt') name, _ = os.path.splitext(srt) srt_out = name + '.srt' convert_to_srt(srt, srt_out) srt = srt_out create_dirs(output) args = [ffmpeg(), '-i', video] if overwrite: args.append('-y') args.extend(['-i', srt]) args.extend(['-map', '0:v', '-map', '0:a']) if skip_eia_608: metadata = extract_metadata(video) for i in (s.index for s in metadata.subtitle_streams if s.codec != 'eia_608'): args.extend(['-map', '0:{}'.format(i)]) else: args.extend(['-map', '0:s?']) args.extend(['-map', '1:0']) if convert: args.extend(['-c:v', 'libx264', '-crf', str(crf), '-preset', preset]) args.extend(['-c:a', 'aac']) else: args.extend(['-c:v', 'copy']) args.extend(['-c:a', 'copy']) args.extend(['-c:s', 'copy']) # -metadata:s:s:0 language=eng if lang: args.extend(['-metadata:s:s:0', 'language=' + lang]) args.append(output) return execute(args)
def select_streams(files, output_file, overwrite=False, convert_config: ConvertConfig = None): from media_management_scripts.support.executables import execute_ffmpeg_with_dialog from media_management_scripts.support.combine_all import get_lang if not overwrite and os.path.exists(output_file): print('Output file exists: {}'.format(output_file)) return if any(file.endswith('.srt') for file in files) and not output_file.endswith('.mkv'): print('Cannot mix an SRT file into a non MKV output') return final_indexes = [] max_duration = 0 subtitle_index_tracker = 0 output_meta = {} for i, file in enumerate(files): if file.endswith('.srt'): is_srt = True lang = get_lang(file) if lang is None: d = Dialog(autowidgetsize=True) exit_code, lang = d.inputbox('Enter language', init='Unknown', title=os.path.basename(file)) if exit_code != d.OK: return else: is_srt = False lang = None metadata = extract_metadata(file) if metadata.estimated_duration and metadata.estimated_duration > max_duration: max_duration = metadata.estimated_duration all_tags = _get_stream_indexes(metadata, lang_override=lang) if all_tags is not None: video_tags, audio_tags, subtitle_tags = all_tags indexes = video_tags + audio_tags + subtitle_tags final_indexes.extend( ['{}:{}'.format(i, index) for index in indexes]) if is_srt and subtitle_tags: output_meta['s:{}'.format(subtitle_index_tracker)] = { 'language': lang } subtitle_index_tracker += len(subtitle_tags) else: # User selected cancel return if max_duration == 0: max_duration = None if convert_config: raise Exception('Convert is not supported in select-streams currently') elif len(final_indexes) > 0: args = create_remux_args(files, output_file, mappings=final_indexes, overwrite=overwrite, metadata=output_meta) if len(files) == 1: title = os.path.basename(files[0]) else: title = 'Remuxing {} files'.format(len(files)) ret = execute_ffmpeg_with_dialog(args, duration=max_duration, title=title) if ret != 0: print('Error executing: {}'.format(args)) else: print('No streams selected.')
def _validate_file(self, filename, lang='eng'): metadata = extract_metadata(filename) self.assertEqual(1, len(metadata.video_streams)) self.assertEqual(1, len(metadata.audio_streams)) self.assertEqual(1, len(metadata.subtitle_streams)) self.assertEqual(lang, metadata.subtitle_streams[0].language)