length argument, set buffer size, aligned console log, calc total delta

This commit is contained in:
Jonathan Baecker 2019-11-08 14:35:40 +01:00
parent 9ecc171645
commit 114186feaa

View File

@ -79,7 +79,7 @@ stdin_parser.add_argument(
) )
stdin_parser.add_argument( stdin_parser.add_argument(
'--loop', help='loop playlist infinitely', action='store_true' '-i', '--loop', help='loop playlist infinitely', action='store_true'
) )
stdin_parser.add_argument( stdin_parser.add_argument(
@ -91,6 +91,11 @@ stdin_parser.add_argument(
help='start time in "hh:mm:ss", "now" for start with first' help='start time in "hh:mm:ss", "now" for start with first'
) )
stdin_parser.add_argument(
'-t', '--length',
help='set length in "hh:mm:ss", "none" for no length check'
)
stdin_args = stdin_parser.parse_args() stdin_args = stdin_parser.parse_args()
@ -117,7 +122,7 @@ def get_time(time_format):
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# read variables from config file # default variables and values from config file
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
_general = SimpleNamespace() _general = SimpleNamespace()
@ -132,6 +137,9 @@ _playout = SimpleNamespace()
_init = SimpleNamespace(load=True) _init = SimpleNamespace(load=True)
_ff = SimpleNamespace(decoder=None, encoder=None) _ff = SimpleNamespace(decoder=None, encoder=None)
_WINDOWS = os.name == 'nt'
COPY_BUFSIZE = 1024 * 1024 if _WINDOWS else 64 * 1024
def load_config(): def load_config():
""" """
@ -142,7 +150,7 @@ def load_config():
cfg = configparser.ConfigParser() cfg = configparser.ConfigParser()
def str_to_sec(s): def str_to_sec(s):
if s in ['now', None, '']: if s in ['now', '', None, 'none']:
return None return None
else: else:
s = s.split(':') s = s.split(':')
@ -167,7 +175,10 @@ def load_config():
if not p_start: if not p_start:
p_start = get_time('full_sec') p_start = get_time('full_sec')
p_length = str_to_sec(cfg.get('PLAYLIST', 'length')) if stdin_args.length:
p_length = str_to_sec(stdin_args.length)
else:
p_length = str_to_sec(cfg.get('PLAYLIST', 'length'))
_general.stop = cfg.getboolean('GENERAL', 'stop_on_error') _general.stop = cfg.getboolean('GENERAL', 'stop_on_error')
_general.threshold = cfg.getfloat('GENERAL', 'stop_threshold') _general.threshold = cfg.getfloat('GENERAL', 'stop_threshold')
@ -264,10 +275,10 @@ class CustomFormatter(logging.Formatter):
message = grey + ' %(message)s' + reset message = grey + ' %(message)s' + reset
FORMATS = { FORMATS = {
logging.DEBUG: timestamp + blue + level + message + reset, logging.DEBUG: timestamp + blue + level + ' ' + message + reset,
logging.INFO: timestamp + green + level + message + reset, logging.INFO: timestamp + green + level + ' ' + message + reset,
logging.WARNING: timestamp + yellow + level + message + reset, logging.WARNING: timestamp + yellow + level + message + reset,
logging.ERROR: timestamp + red + level + message + reset logging.ERROR: timestamp + red + level + ' ' + message + reset
} }
def format_message(self, msg): def format_message(self, msg):
@ -509,9 +520,9 @@ def terminate_processes(watcher=None):
watcher.stop() watcher.stop()
def decoder_error_reader(pipe): def decoder_error_reader(std_errors):
try: try:
for line in pipe.stderr: for line in std_errors:
messenger.error('[decoder] {}'.format(line.decode("utf-8"))) messenger.error('[decoder] {}'.format(line.decode("utf-8")))
except ValueError: except ValueError:
pass pass
@ -565,6 +576,18 @@ def valid_json(file):
return None return None
def check_sync(delta):
"""
check that we are in tolerance time
"""
if _general.stop and abs(delta) > _general.threshold:
messenger.error(
'Sync tolerance value exceeded with {0:.2f} seconds,\n'
'program terminated!'.format(delta))
terminate_processes()
sys.exit(1)
def check_length(json_nodes, total_play_time): def check_length(json_nodes, total_play_time):
""" """
check if playlist is long enough check if playlist is long enough
@ -751,49 +774,54 @@ def src_or_dummy(src, dur, seek, out):
return gen_dummy(out - seek) return gen_dummy(out - seek)
def get_delta(begin, seek, first): def get_current_delta(begin, target_playtime):
""" """
get difference between current time and begin from clip in playlist get difference between current time and begin from clip in playlist
""" """
if _playlist.length:
target_playtime = _playlist.length
else:
target_playtime = 86400.0
current_time = get_time('full_sec') current_time = get_time('full_sec')
if _playlist.start >= current_time and not begin == _playlist.start: if _playlist.start >= current_time and not begin == _playlist.start:
current_time += target_playtime current_time += target_playtime
if first: current_delta = begin - current_time
time_delta = begin + seek - current_time
if math.isclose(current_delta, 86400.0, abs_tol=6):
current_delta -= 86400.0
return current_delta
def handle_list_init(current_delta, total_delta, src, dur, seek, out):
"""
# handle init clip, but this clip can be the last one in playlist,
# this we have to figure out and calculate the right length
"""
new_seek = abs(current_delta) + seek
new_out = out
if 1 > new_seek:
new_seek = 0
if out - new_seek > total_delta:
new_out = total_delta + new_seek
if total_delta > new_out - new_seek > 1:
return src_or_dummy(
src, dur, new_seek, new_out), new_seek, new_out, False
elif new_out - new_seek > 1:
return src_or_dummy(
src, dur, new_seek, new_out), new_seek, new_out, True
else: else:
time_delta = begin - current_time return None, 0, 0, True
if math.isclose(time_delta, 86400.0, abs_tol=6):
time_delta -= 86400.0
if not first and not stdin_args.loop:
# check that we are in tolerance time
if _general.stop and abs(time_delta) > _general.threshold:
messenger.error(
'Sync tolerance value exceeded with {0:.2f} seconds,\n'
'program terminated!'.format(time_delta))
terminate_processes()
sys.exit(1)
messenger.debug('time_delta: {}'.format(time_delta))
return target_playtime, time_delta
def handle_list_end(time_delta, ref_time, src, begin, dur, seek, out): def handle_list_end(new_length, src, begin, dur, seek, out):
""" """
when we come to last clip in playlist, when we come to last clip in playlist,
or when we reached total playtime, or when we reached total playtime,
we end up here we end up here
""" """
new_length = ref_time - (begin + time_delta)
new_out = out new_out = out
new_playlist = True new_playlist = True
@ -838,33 +866,41 @@ def timed_source(src, begin, dur, seek, out, first, last):
check begin and length from clip check begin and length from clip
return clip only if we are in 24 hours time range return clip only if we are in 24 hours time range
""" """
if _playlist.length:
target_playtime = _playlist.length
else:
target_playtime = 86400.0
target_playtime, time_delta = get_delta(begin, seek, first) current_delta = get_current_delta(begin, target_playtime)
ref_time = target_playtime + _playlist.start ref_time = target_playtime + _playlist.start
total_delta = ref_time - begin + current_delta
if first: if first:
new_seek = abs(time_delta) return handle_list_init(current_delta, total_delta,
if 1 > new_seek: src, dur, seek, out)
new_seek = 0
return src_or_dummy(src, dur, new_seek, out), new_seek, out, False
if (begin + out + time_delta < ref_time and not last) \
or not _playlist.length or stdin_args.loop:
# when we are in the 24 houre range, get the clip
return src_or_dummy(src, dur, seek, out), seek, out, False
elif begin + time_delta > ref_time:
messenger.info(
'Start time is over {}, skip clip:\n{}'.format(
timedelta(seconds=target_playtime), src))
return None, 0, 0, True
elif begin + out + time_delta > ref_time or last:
return handle_list_end(time_delta, ref_time, src,
begin, dur, seek, out)
else: else:
return None, 0, 0, True if not stdin_args.loop:
check_sync(current_delta)
messenger.debug('current_delta: {:f}'.format(current_delta))
messenger.debug('total_delta: {:f}'.format(total_delta))
if (total_delta > out - seek and not last) \
or stdin_args.loop or not _playlist.length:
# when we are in the 24 houre range, get the clip
return src_or_dummy(src, dur, seek, out), seek, out, False
elif total_delta <= 0:
messenger.info(
'Start time is over {}, skip clip:\n{}'.format(
timedelta(seconds=target_playtime), src))
return None, 0, 0, True
elif total_delta < out - seek or last:
return handle_list_end(total_delta, src, begin, dur, seek, out)
else:
return None, 0, 0, True
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
@ -1599,13 +1635,13 @@ def main():
stdout=PIPE, stderr=PIPE) as _ff.decoder: stdout=PIPE, stderr=PIPE) as _ff.decoder:
err_thread = Thread(target=decoder_error_reader, err_thread = Thread(target=decoder_error_reader,
args=(_ff.decoder,)) args=(_ff.decoder.stderr,))
err_thread.daemon = True err_thread.daemon = True
err_thread.start() err_thread.start()
while True: while True:
buf = _ff.decoder.stdout.read(65424) buf = _ff.decoder.stdout.read(COPY_BUFSIZE)
if not buf and _ff.decoder.poll() is not None: if not buf:
break break
_ff.encoder.stdin.write(buf) _ff.encoder.stdin.write(buf)