Пример #1
0
def clean_ts():
    """
    this function get all *.m3u8 playlists from config,
    read lines from them until it founds first *.ts file,
    then it checks if files on hard drive are older then this first *.ts
    and if so delete them
    """
    m3u8_files = [p for p in playout.hls_output if 'm3u8' in p]

    for m3u8_file in m3u8_files:
        messenger.debug(f'cleanup *.ts files from: "{m3u8_file}"')
        test_num = 0
        hls_path = os.path.dirname(m3u8_file)

        if os.path.isfile(m3u8_file):
            with open(m3u8_file, 'r') as m3u8:
                for line in m3u8:
                    if '.ts' in line:
                        test_num = int(re.findall(r'(\d+).ts', line)[0])
                        break

            for ts_file in iglob(os.path.join(hls_path, '*.ts')):
                ts_num = int(re.findall(r'(\d+).ts', ts_file)[0])

                if test_num > ts_num:
                    try:
                        os.remove(ts_file)
                    except OSError:
                        pass
Пример #2
0
def output():
    """
    this output is for streaming to a target address,
    like rtmp, rtp, svt, etc.
    """
    year = get_date(False).split('-')[0]
    overlay = []

    ff_pre_settings = [
        '-pix_fmt', 'yuv420p', '-r',
        str(_pre.fps), '-c:v', 'mpeg2video', '-intra', '-b:v', '{}k'.format(
            _pre.v_bitrate), '-minrate', '{}k'.format(_pre.v_bitrate),
        '-maxrate', '{}k'.format(_pre.v_bitrate), '-bufsize', '{}k'.format(
            _pre.v_bufsize)
    ] + pre_audio_codec() + ['-f', 'mpegts', '-']

    if _text.add_text and not _text.over_pre:
        messenger.info('Using drawtext node, listening on address: {}'.format(
            _text.address))
        overlay = [
            '-vf',
            "null,zmq=b=tcp\\\\://'{}',drawtext=text='':fontfile='{}'".format(
                _text.address.replace(':', '\\:'), _text.fontfile)
        ]

    try:
        _ff.encoder = Popen([
            'ffmpeg', '-v',
            _log.ff_level.lower(), '-hide_banner', '-nostats', '-re',
            '-thread_queue_size', '256', '-i', 'pipe:0'
        ] + overlay + [
            '-metadata', 'service_name=' + _playout.name, '-metadata',
            'service_provider=' + _playout.provider, '-metadata',
            'year={}'.format(year)
        ] + _playout.ffmpeg_param + _playout.stream_output,
                            stdin=PIPE,
                            stderr=PIPE)

        enc_err_thread = Thread(target=ffmpeg_stderr_reader,
                                args=(_ff.encoder.stderr, False))
        enc_err_thread.daemon = True
        enc_err_thread.start()

        if _playlist.mode and not stdin_args.folder:
            watcher = None
            get_source = GetSourceFromPlaylist()
        else:
            messenger.info('Start folder mode')
            media = MediaStore()
            watcher = MediaWatcher(media)
            get_source = GetSourceFromFolder(media)

        try:
            for src_cmd in get_source.next():
                messenger.debug('src_cmd: "{}"'.format(src_cmd))
                if src_cmd[0] == '-i':
                    current_file = src_cmd[1]
                else:
                    current_file = src_cmd[3]

                _current.clip = current_file
                messenger.info('Play: "{}"'.format(current_file))

                with Popen([
                        'ffmpeg', '-v',
                        _log.ff_level.lower(), '-hide_banner', '-nostats'
                ] + src_cmd + ff_pre_settings,
                           stdout=PIPE,
                           stderr=PIPE) as _ff.decoder:

                    dec_err_thread = Thread(target=ffmpeg_stderr_reader,
                                            args=(_ff.decoder.stderr, True))
                    dec_err_thread.daemon = True
                    dec_err_thread.start()

                    while True:
                        buf = _ff.decoder.stdout.read(COPY_BUFSIZE)
                        if not buf:
                            break
                        _ff.encoder.stdin.write(buf)

        except BrokenPipeError:
            messenger.error('Broken Pipe!')
            terminate_processes(watcher)

        except SystemExit:
            messenger.info('Got close command')
            terminate_processes(watcher)

        except KeyboardInterrupt:
            messenger.warning('Program terminated')
            terminate_processes(watcher)

        # close encoder when nothing is to do anymore
        if _ff.encoder.poll() is None:
            _ff.encoder.terminate()

    finally:
        if _ff.encoder.poll() is None:
            _ff.encoder.terminate()
        _ff.encoder.wait()
Пример #3
0
def output():
    """
    this output is for playing on desktop with ffplay
    """
    overlay = []

    ff_pre_settings = [
        '-pix_fmt', 'yuv420p', '-r',
        str(_pre.fps), '-c:v', 'mpeg2video', '-intra', '-b:v',
        f'{_pre.v_bitrate}k', '-minrate', f'{_pre.v_bitrate}k', '-maxrate',
        f'{_pre.v_bitrate}k', '-bufsize', f'{_pre.v_bufsize}k'
    ] + pre_audio_codec() + ['-f', 'mpegts', '-']

    if _text.add_text and not _text.over_pre:
        messenger.info(
            f'Using drawtext node, listening on address: {_text.address}')
        overlay = [
            '-vf',
            "null,zmq=b=tcp\\\\://'{}',drawtext=text='':fontfile='{}'".format(
                _text.address.replace(':', '\\:'), _text.fontfile)
        ]

    try:
        enc_cmd = ['ffplay', '-hide_banner', '-nostats', '-i', 'pipe:0'
                   ] + overlay

        messenger.debug(f'Encoder CMD: "{" ".join(enc_cmd)}"')

        _ff.encoder = Popen(enc_cmd, stderr=PIPE, stdin=PIPE, stdout=None)

        enc_err_thread = Thread(target=ffmpeg_stderr_reader,
                                args=(_ff.encoder.stderr, False))
        enc_err_thread.daemon = True
        enc_err_thread.start()

        if _playlist.mode and not stdin_args.folder:
            watcher = None
            get_source = GetSourceFromPlaylist()
        else:
            messenger.info('Start folder mode')
            media = MediaStore()
            watcher = MediaWatcher(media)
            get_source = GetSourceFromFolder(media)

        try:
            for node in get_source.next():
                if watcher is not None:
                    watcher.current_clip = node.get('source')

                messenger.info(f'Play for {node["out"] - node["seek"]:.2f} '
                               f'seconds: {node.get("source")}')

                dec_cmd = [
                    'ffmpeg', '-v',
                    _log.ff_level.lower(), '-hide_banner', '-nostats'
                ] + node['src_cmd'] + node['filter'] + ff_pre_settings

                messenger.debug(f'Decoder CMD: "{" ".join(dec_cmd)}"')

                with Popen(dec_cmd, stdout=PIPE, stderr=PIPE) as _ff.decoder:
                    dec_err_thread = Thread(target=ffmpeg_stderr_reader,
                                            args=(_ff.decoder.stderr, True))
                    dec_err_thread.daemon = True
                    dec_err_thread.start()

                    while True:
                        buf = _ff.decoder.stdout.read(COPY_BUFSIZE)
                        if not buf:
                            break
                        _ff.encoder.stdin.write(buf)

        except BrokenPipeError:
            messenger.error('Broken Pipe!')
            terminate_processes(watcher)

        except SystemExit:
            messenger.info('Got close command')
            terminate_processes(watcher)

        except KeyboardInterrupt:
            messenger.warning('Program terminated')
            terminate_processes(watcher)

        # close encoder when nothing is to do anymore
        if _ff.encoder.poll() is None:
            _ff.encoder.terminate()

    finally:
        if _ff.encoder.poll() is None:
            _ff.encoder.terminate()
        _ff.encoder.wait()
Пример #4
0
def output():
    """
    this output is hls output, no pre-process is needed.
    """
    year = get_date(False).split('-')[0]
    sync_op.realtime = True

    try:
        if playlist.mode and not stdin_args.folder:
            watcher = None
            get_source = GetSourceFromPlaylist()
        else:
            messenger.info('Start folder mode')
            media = MediaStore()
            watcher = MediaWatcher(media)
            get_source = GetSourceFromFolder(media)

        try:
            for node in get_source.next():
                if watcher is not None:
                    watcher.current_clip = node.get('source')

                messenger.info(f'Play: {node.get("source")}')

                cmd = [
                    'ffmpeg', '-v', log.ff_level.lower(), '-hide_banner',
                    '-nostats'
                    ] + node['src_cmd'] + node['filter'] + [
                        '-metadata', 'service_name=' + playout.name,
                        '-metadata', 'service_provider=' + playout.provider,
                        '-metadata', 'year={}'.format(year)
                    ] + playout.ffmpeg_param + playout.hls_output

                messenger.debug(f'Encoder CMD: "{" ".join(cmd)}"')

                ff_proc.encoder = Popen(cmd, stdin=PIPE, stderr=PIPE)

                stderr_reader_thread = Thread(target=ffmpeg_stderr_reader,
                                              args=(ff_proc.encoder.stderr,
                                                    False))
                stderr_reader_thread.daemon = True
                stderr_reader_thread.start()
                stderr_reader_thread.join()

                ts_cleaning_thread = Thread(target=clean_ts)
                ts_cleaning_thread.daemon = True
                ts_cleaning_thread.start()

        except BrokenPipeError:
            messenger.error('Broken Pipe!')
            terminate_processes(watcher)

        except SystemExit:
            messenger.info('Got close command')
            terminate_processes(watcher)

        except KeyboardInterrupt:
            messenger.warning('Program terminated')
            terminate_processes(watcher)

        # close encoder when nothing is to do anymore
        if ff_proc.encoder.poll() is None:
            ff_proc.encoder.terminate()

    finally:
        if ff_proc.encoder.poll() is None:
            ff_proc.encoder.terminate()
        ff_proc.encoder.wait()
Пример #5
0
def output():
    """
    this output is hls output, no preprocess is needed.
    """
    year = get_date(False).split('-')[0]

    try:
        if _playlist.mode and not stdin_args.folder:
            watcher = None
            get_source = GetSourceFromPlaylist()
        else:
            messenger.info('Start folder mode')
            media = MediaStore()
            watcher = MediaWatcher(media)
            get_source = GetSourceFromFolder(media)

        try:
            for src_cmd in get_source.next():
                messenger.debug('src_cmd: "{}"'.format(src_cmd))
                if src_cmd[0] == '-i':
                    current_file = src_cmd[1]
                else:
                    current_file = src_cmd[3]

                messenger.info('Play: "{}"'.format(current_file))
                cmd = [
                    'ffmpeg', '-v', _log.ff_level.lower(), '-hide_banner',
                    '-nostats'
                    ] + src_cmd + [
                        '-metadata', 'service_name=' + _playout.name,
                        '-metadata', 'service_provider=' + _playout.provider,
                        '-metadata', 'year={}'.format(year)
                    ] + _playout.ffmpeg_param + _playout.hls_output

                _ff.encoder = Popen(cmd, stdin=PIPE, stderr=PIPE)

                stderr_reader_thread = Thread(target=ffmpeg_stderr_reader,
                                              args=(_ff.encoder.stderr, False))
                stderr_reader_thread.daemon = True
                stderr_reader_thread.start()
                stderr_reader_thread.join()

                ts_cleaning_thread = Thread(target=clean_ts)
                ts_cleaning_thread.daemon = True
                ts_cleaning_thread.start()

        except BrokenPipeError:
            messenger.error('Broken Pipe!')
            terminate_processes(watcher)

        except SystemExit:
            messenger.info('Got close command')
            terminate_processes(watcher)

        except KeyboardInterrupt:
            messenger.warning('Program terminated')
            terminate_processes(watcher)

        # close encoder when nothing is to do anymore
        if _ff.encoder.poll() is None:
            _ff.encoder.terminate()

    finally:
        if _ff.encoder.poll() is None:
            _ff.encoder.terminate()
        _ff.encoder.wait()
Пример #6
0
def output():
    """
    this output is for streaming to a target address,
    like rtmp, rtp, svt, etc.
    """
    year = get_date(False).split('-')[0]
    overlay = []

    ff_pre_settings = [
        '-pix_fmt', 'yuv420p', '-r',
        str(pre.fps), '-c:v', 'mpeg2video', '-intra', '-b:v',
        f'{pre.v_bitrate}k', '-minrate', f'{pre.v_bitrate}k', '-maxrate',
        f'{pre.v_bitrate}k', '-bufsize', f'{pre.v_bufsize}k'
    ] + pre_audio_codec() + ['-f', 'mpegts', '-']

    if lower_third.add_text and not lower_third.over_pre:
        messenger.info(
            f'Using drawtext node, listening on address: {lower_third.address}'
        )
        overlay = [
            '-vf',
            "null,zmq=b=tcp\\\\://'{}',drawtext=text='':fontfile='{}'".format(
                lower_third.address.replace(':', '\\:'), lower_third.fontfile)
        ]

    try:
        enc_cmd = [
            'ffmpeg', '-v',
            log.ff_level.lower(), '-hide_banner', '-nostats', '-re',
            '-thread_queue_size', '160', '-i', 'pipe:0'
        ] + overlay + [
            '-metadata', 'service_name=' + playout.name, '-metadata',
            'service_provider=' + playout.provider, '-metadata', f'year={year}'
        ] + playout.ffmpeg_param + playout.stream_output

        messenger.debug(f'Encoder CMD: "{" ".join(enc_cmd)}"')

        ff_proc.encoder = Popen(enc_cmd, stdin=PIPE, stderr=PIPE)

        enc_err_thread = Thread(target=ffmpeg_stderr_reader,
                                args=(ff_proc.encoder.stderr, False))
        enc_err_thread.daemon = True
        enc_err_thread.start()

        if playlist.mode and not stdin_args.folder:
            watcher = None
            get_source = GetSourceFromPlaylist()
        else:
            messenger.info('Start folder mode')
            media = MediaStore()
            watcher = MediaWatcher(media)
            get_source = GetSourceFromFolder(media)

        try:
            for node in get_source.next():
                if watcher is not None:
                    watcher.current_clip = node.get('source')

                messenger.info(f'Play: {node.get("source")}')

                dec_cmd = [
                    'ffmpeg', '-v',
                    log.ff_level.lower(), '-hide_banner', '-nostats'
                ] + node['src_cmd'] + node['filter'] + ff_pre_settings

                messenger.debug(f'Decoder CMD: "{" ".join(dec_cmd)}"')

                with Popen(dec_cmd, stdout=PIPE,
                           stderr=PIPE) as ff_proc.decoder:
                    dec_err_thread = Thread(target=ffmpeg_stderr_reader,
                                            args=(ff_proc.decoder.stderr,
                                                  True))
                    dec_err_thread.daemon = True
                    dec_err_thread.start()

                    while True:
                        buf = ff_proc.decoder.stdout.read(COPY_BUFSIZE)
                        if not buf:
                            break
                        ff_proc.encoder.stdin.write(buf)

        except BrokenPipeError:
            messenger.error('Broken Pipe!')
            terminate_processes(watcher)

        except SystemExit:
            messenger.info('Got close command')
            terminate_processes(watcher)

        except KeyboardInterrupt:
            messenger.warning('Program terminated')
            terminate_processes(watcher)

        # close encoder when nothing is to do anymore
        if ff_proc.encoder.poll() is None:
            ff_proc.encoder.terminate()

    finally:
        if ff_proc.encoder.poll() is None:
            ff_proc.encoder.terminate()
        ff_proc.encoder.wait()