Exemplo n.º 1
0
    def testCodecCopyWithSplit(self):
        """ Проверяется корректность использования vcodec=copy совместно
        фильтрами для видео."""
        ff = FFMPEG(inputfile=SourceFile('/tmp/input.mp4'))

        fc = ff.init_filter_complex()

        fc.video | filters.Scale(640, 360) | fc.get_video_dest(0)

        cv0 = VideoCodec(map='0:v', vcodec='copy')
        ca0 = AudioCodec(map='0:a', acodec='copy')
        out0 = SimpleMuxer('flv')('/tmp/copy.flv')
        ff.add_output(out0, cv0, ca0)

        cv1 = VideoCodec(vcodec='libx264')
        ca1 = AudioCodec(acodec='aac')
        out1 = SimpleMuxer('flv')('/tmp/out.flv')
        ff.add_output(out1, cv1, ca1)

        expected = [
            'ffmpeg', '-i', '/tmp/input.mp4', '-filter_complex',
            '[0:v]scale=640x360[vout0]', '-map', '0:v', '-c:v', 'copy', '-map',
            '0:a', '-c:a', 'copy', '-f', 'flv', '/tmp/copy.flv', '-map',
            '[vout0]', '-c:v', 'libx264', '-map', '0:a', '-c:a', 'aac', '-f',
            'flv', '/tmp/out.flv'
        ]
        self.assertEqual(ff.get_args(), ensure_binary(expected))
Exemplo n.º 2
0
    def testInputSkipStreams(self):
        """ Проверка корректности наименования входных потоков в фильтрах."""

        ff = FFMPEG()
        ff < SourceFile('/tmp/input.jpg', audio_streams=0)
        ff < SourceFile('/tmp/input.mp4')
        fc = ff.init_filter_complex()
        overlay = filters.Overlay(0, 0)
        fc.video | filters.Scale(640, 360) | overlay
        fc.video | filters.Scale(1280, 720) | overlay
        fc.audio | filters.Volume(-20) | fc.get_audio_dest(0)
        overlay | fc.get_video_dest(0)

        cv0 = VideoCodec(vcodec='libx264', vbitrate='700000', size='640x360')
        ca0 = AudioCodec(acodec='aac', abitrate='128000')
        out0 = SimpleMuxer('flv')('/tmp/out.flv')
        ff.add_output(out0, cv0, ca0)

        expected = [
            'ffmpeg', '-i', '/tmp/input.jpg', '-i', '/tmp/input.mp4',
            '-filter_complex',
            ('[0:v]scale=640x360[v:scale0];'
             '[v:scale0][v:overlay0]overlay=x=0:y=0[vout0];'
             '[1:v]scale=1280x720[v:overlay0];'
             '[1:a]volume=-20.00[aout0]'), '-map', '[vout0]', '-c:v',
            'libx264', '-b:v', '700000', '-map', '[aout0]', '-c:a', 'aac',
            '-b:a', '128000', '-f', 'flv', '/tmp/out.flv'
        ]
        self.assertEqual(ff.get_args(), ensure_binary(expected))
Exemplo n.º 3
0
    def testFFMPEG(self):
        """ Проверка работоспособности и демонстрация возможностей."""
        ff = FFMPEG()
        ff < SourceFile('/tmp/input.mp4')

        fc = ff.init_filter_complex()

        asplit = fc.audio | filters.AudioSplit()

        fc.video | filters.Scale(640, 360) | fc.get_video_dest(0)

        asplit.connect_dest(fc.get_audio_dest(0))
        asplit.connect_dest(fc.get_audio_dest(1))

        out0 = SimpleMuxer('flv')('/tmp/out.flv')
        out1 = SimpleMuxer('mp3')('/tmp/out.mp3')

        cv0 = VideoCodec(vcodec='libx264', vbitrate='700000', size='640x360')
        ca0 = AudioCodec(acodec='aac', abitrate='128000')
        ca1 = AudioCodec(acodec='libmp3lame', abitrate='394000')

        ff.add_output(out0, cv0, ca0)
        ff.add_output(out1, ca1)

        expected = [
            'ffmpeg', '-i', '/tmp/input.mp4', '-filter_complex',
            '[0:v]scale=640x360[vout0];[0:a]asplit[aout0][aout1]', '-map',
            '[vout0]', '-c:v', 'libx264', '-b:v', '700000', '-map', '[aout0]',
            '-c:a', 'aac', '-b:a', '128000', '-f', 'flv', '/tmp/out.flv',
            '-map', '[aout1]', '-c:a', 'libmp3lame', '-b:a', '394000', '-f',
            'mp3', '/tmp/out.mp3'
        ]
        self.assertEqual(ff.get_args(), ensure_binary(expected))
Exemplo n.º 4
0
    def testReuseInputFiles(self):
        """ Проверяет что входные файлы можно использовать несколько раз."""
        ff = FFMPEG(inputfile=SourceFile('/tmp/input.mp4'))
        cv0 = VideoCodec(map='0:v', vcodec='copy')
        ca0 = AudioCodec(map='0:a', acodec='copy')
        out0 = SimpleMuxer('flv')('/tmp/out0.flv')
        ff.add_output(out0, cv0, ca0)

        cv1 = VideoCodec(map='0:v', vcodec='copy')
        ca1 = AudioCodec(map='0:a', acodec='copy')
        out1 = SimpleMuxer('flv')('/tmp/out1.flv')
        ff.add_output(out1, cv1, ca1)
        expected = [
            'ffmpeg',
            '-i',
            '/tmp/input.mp4',
            '-map',
            '0:v',
            '-c:v',
            'copy',
            '-map',
            '0:a',
            '-c:a',
            'copy',
            '-f',
            'flv',
            '/tmp/out0.flv',
            '-map',
            '0:v',
            '-c:v',
            'copy',
            '-map',
            '0:a',
            '-c:a',
            'copy',
            '-f',
            'flv',
            '/tmp/out1.flv',
        ]
        self.assertEqual(ff.get_args(), ensure_binary(expected))
Exemplo n.º 5
0
    def testBypassWithoutFilterComplex(self):
        """ Проверка работы в режиме bypass, когда вообще нет filter_complex."""
        ff = FFMPEG(inputfile=SourceFile('/tmp/input.mp4'))

        cv0 = VideoCodec(vcodec='libx264', vbitrate='700000', size='640x360')
        ca0 = AudioCodec(acodec='aac', abitrate='128000')
        out0 = SimpleMuxer('flv')('/tmp/out.flv')
        ff.add_output(out0, cv0, ca0)

        expected = [
            'ffmpeg', '-i', '/tmp/input.mp4', '-map', '0:v', '-c:v', 'libx264',
            '-b:v', '700000', '-map', '0:a', '-c:a', 'aac', '-b:a', '128000',
            '-f', 'flv', '/tmp/out.flv'
        ]
        self.assertEqual(ff.get_args(), ensure_binary(expected))
Exemplo n.º 6
0
    def testHLSMuxer(self):
        ff = FFMPEG(inputfile=SourceFile('/tmp/input.mp4'))

        cv0 = VideoCodec(vcodec='libx264')
        ca0 = AudioCodec(acodec='aac')
        out0 = HLSMuxer('http://ya.ru/out.m3u8',
                        segment_size=4,
                        manifest_size=5,
                        method='PUT')
        ff.add_output(out0, cv0, ca0)
        expected = [
            'ffmpeg', '-i', '/tmp/input.mp4', '-map', '0:v', '-c:v', 'libx264',
            '-map', '0:a', '-c:a', 'aac', '-f', 'hls', '-method', 'PUT',
            '-hls_time', '4', '-hls_list_size', '5', 'http://ya.ru/out.m3u8'
        ]
        self.assertEqual(ff.get_args(), ensure_binary(expected))
Exemplo n.º 7
0
    def testTeeMuxer(self):
        ff = FFMPEG(inputfile=SourceFile('/tmp/input.mp4'))

        cv0 = VideoCodec(vcodec='libx264')
        ca0 = AudioCodec(acodec='aac')
        out0 = HLSMuxer('http://ya.ru/1.m3u8', segment_size=2)

        out1 = HLSMuxer('http://ya.ru/2.m3u8', manifest_size=5)
        ff.add_output(TeeMuxer(out0, out1), cv0, ca0)

        expected = [
            'ffmpeg', '-i', '/tmp/input.mp4', '-map', '0:v', '-c:v', 'libx264',
            '-map', '0:a', '-c:a', 'aac', '-f', 'tee',
            '[f=hls:hls_time=2]http://ya.ru/1.m3u8|'
            '[f=hls:hls_list_size=5]http://ya.ru/2.m3u8'
        ]
        self.assertEqual(ff.get_args(), ensure_binary(expected))
Exemplo n.º 8
0
    def transcode(self) -> None:
        """ Transcodes video

        * checks source mediainfo
        * runs `ffmpeg`
        * validates result
        """
        # Get source mediainfo to use in validation
        source_media_info = self.get_media_info(self.source)

        # Common ffmpeg flags
        ff = FFMPEG(overwrite=True, loglevel='repeat+level+info')
        # Init source file
        ff < SourceFile(self.source)
        # Scaling
        fc = ff.init_filter_complex()
        fc.video | Scale(**TRANSCODING_OPTIONS[SCALE]) | fc.get_video_dest(0)

        # set group of pixels length to segment size
        gop = math.floor(source_media_info[VIDEO_FRAME_RATE] * GOP_DURATION)
        # preserve source audio sampling rate
        arate = source_media_info[AUDIO_SAMPLING_RATE]
        # preserve original video FPS
        vrate = source_media_info[VIDEO_FRAME_RATE]
        # codecs, muxer and output path

        cv0 = VideoCodec(gop=gop,
                         vrate=vrate,
                         **TRANSCODING_OPTIONS[VIDEO_CODEC])
        ca0 = AudioCodec(arate=arate, **TRANSCODING_OPTIONS[AUDIO_CODEC])
        out0 = Muxer(self.destination, format='mp4')

        # Add output file to ffmpeg
        ff.add_output(out0, cv0, ca0)

        # Run ffmpeg
        self.run(ff)

        # Get result mediainfo
        dest_media_info = self.get_media_info(self.destination)

        # Validate ffmpeg result
        self.validate(source_media_info, dest_media_info)
Exemplo n.º 9
0
    def testBypassWithFilterComplex(self):
        """ Проверка работы в режиме bypass, когда аудиопоток не проходит ни
        через один фильтр."""
        ff = FFMPEG(inputfile=SourceFile('/tmp/input.mp4'))

        fc = ff.init_filter_complex()
        fc.video | filters.Scale(640, 360) | fc.get_video_dest(0)

        cv0 = VideoCodec(vcodec='libx264', vbitrate='700000', size='640x360')
        ca0 = AudioCodec(acodec='aac', abitrate='128000')
        out0 = SimpleMuxer('flv')('/tmp/out.flv')
        ff.add_output(out0, cv0, ca0)

        expected = [
            'ffmpeg', '-i', '/tmp/input.mp4', '-filter_complex',
            '[0:v]scale=640x360[vout0]', '-map', '[vout0]', '-c:v', 'libx264',
            '-b:v', '700000', '-map', '0:a', '-c:a', 'aac', '-b:a', '128000',
            '-f', 'flv', '/tmp/out.flv'
        ]
        self.assertEqual(ff.get_args(), ensure_binary(expected))
Exemplo n.º 10
0
    def testCodecCopy(self):
        """ Проверяется корректность использования vcodec=copy совместно с
        фильтрами для аудио."""
        ff = FFMPEG(inputfile=SourceFile('/tmp/input.mp4'))

        fc = ff.init_filter_complex()

        fc.audio | filters.Volume(20) | fc.get_audio_dest(0)

        cv0 = VideoCodec(vcodec='copy')
        ca0 = AudioCodec(acodec='aac', abitrate='128000')
        out0 = SimpleMuxer('flv')('/tmp/out.flv')
        ff.add_output(out0, cv0, ca0)
        expected = [
            'ffmpeg', '-i', '/tmp/input.mp4', '-filter_complex',
            '[0:a]volume=20.00[aout0]', '-map', '0:v', '-c:v', 'copy', '-map',
            '[aout0]', '-c:a', 'aac', '-b:a', '128000', '-f', 'flv',
            '/tmp/out.flv'
        ]
        self.assertEqual(ff.get_args(), ensure_binary(expected))