예제 #1
0
    def __init__(self):
        self.init_time = _playlist.start
        self.last_time = get_time('full_sec')

        if _playlist.length:
            self.total_playtime = _playlist.length
        else:
            self.total_playtime = 86400.0

        if self.last_time < _playlist.start:
            self.last_time += self.total_playtime

        self.last_mod_time = 0.0
        self.json_file = None
        self.clip_nodes = None
        self.src_cmd = None
        self.probe = MediaProbe()
        self.filtergraph = []
        self.first = True
        self.last = False
        self.list_date = get_date(True)

        self.src = None
        self.begin = 0
        self.seek = 0
        self.out = 20
        self.duration = 20
        self.ad = False
        self.ad_last = False
        self.ad_next = False
예제 #2
0
    def eof_handling(self, message, fill, duration=None):
        self.seek = 0.0
        self.ad = False

        messenger.error(message)

        if duration:
            self.out = duration
            self.duration = duration
            self.first = True
        else:
            current_delta, total_delta = get_delta(self.begin)
            self.out = abs(total_delta)
            self.duration = abs(total_delta)
            self.first = False

        self.list_date = get_date(False)
        self.last_mod_time = 0.0
        self.last_time = 0.0

        if self.duration > 2 and fill:
            self.probe, self.src_cmd = gen_filler(self.duration)
            self.set_filtergraph()

        else:
            self.src_cmd = None
            self.next_playlist = True

        self.last = False
예제 #3
0
 def check_for_next_playlist(self):
     if not self.next_playlist:
         # normal behavior, when no new playlist is needed
         self.last_time = self.begin
     elif self.next_playlist and _playlist.length != 86400.0:
         # get sure that no new clip will be loaded
         self.last_time = 86400.0 * 2
     else:
         # when there is no time left and we are in time,
         # set right values for new playlist
         self.list_date = get_date(False)
         self.last_mod_time = 0.0
         self.last_time = _playlist.start - 1
예제 #4
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()
예제 #5
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()
예제 #6
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()
예제 #7
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()