cleanup code
This commit is contained in:
parent
ed8cce9420
commit
7de4f96dc5
@ -15,7 +15,6 @@
|
|||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
# set playlist_mode to False if you want to play clips from the [FOLDER] section
|
|
||||||
|
|
||||||
# sometimes it can happen, that a file is corrupt but still playable,
|
# sometimes it can happen, that a file is corrupt but still playable,
|
||||||
# this can produce an streaming error over all following files
|
# this can produce an streaming error over all following files
|
||||||
@ -24,7 +23,6 @@
|
|||||||
# best way is a systemd serivce on linux
|
# best way is a systemd serivce on linux
|
||||||
# stop_threshold: stop ffplayout, if it is async in time above this value
|
# stop_threshold: stop ffplayout, if it is async in time above this value
|
||||||
[GENERAL]
|
[GENERAL]
|
||||||
playlist_mode = True
|
|
||||||
stop_on_error = True
|
stop_on_error = True
|
||||||
stop_threshold = 11
|
stop_threshold = 11
|
||||||
|
|
||||||
@ -74,32 +72,33 @@ ffmpeg_copy_settings = ["-c", "copy", "-bsf:v", "h264_mp4toannexb", "-f", "mpegt
|
|||||||
|
|
||||||
|
|
||||||
# playlist settings
|
# playlist settings
|
||||||
|
# set playlist_mode to False if you want to play clips from the [STORAGE] section
|
||||||
|
|
||||||
# put only the root path here, for example: "/playlists"
|
# put only the root path here, for example: "/playlists"
|
||||||
# subfolders are readed by the script
|
# subfolders are readed by the script
|
||||||
# subfolders needs this structur:
|
# subfolders needs this structur:
|
||||||
# "/playlists/2018/01" (/playlists/year/month)
|
# "/playlists/2018/01" (/playlists/year/month)
|
||||||
# strings in playlist must have ampersan (&) as: &
|
|
||||||
|
|
||||||
# day_start means at which time the playlist should start
|
# day_start means at which time the playlist should start
|
||||||
# leave day_start blank when playlist should always start at the begin
|
# leave day_start blank when playlist should always start at the begin
|
||||||
|
[PLAYLIST]
|
||||||
|
playlist_mode = True
|
||||||
|
path = /playlists
|
||||||
|
day_start = 05:59:25.000
|
||||||
|
|
||||||
|
|
||||||
|
# play ordered or ramdomly files from path
|
||||||
|
# extensions: search only files with this extension, can be a list
|
||||||
|
# set shuffle to True to pick files randomly
|
||||||
# filler_path are for the GUI only at the moment
|
# filler_path are for the GUI only at the moment
|
||||||
# filler_clip is for fill the end to reach 24 hours, it will loop when is necessary
|
# filler_clip is for fill the end to reach 24 hours, it will loop when is necessary
|
||||||
# blackclip is for stream copy mode,
|
# blackclip is for stream copy mode,
|
||||||
# best for this is a ~4 hours clip with black color and soft noise sound
|
# best for this is a ~4 hours clip with black color and soft noise sound
|
||||||
[PLAYLIST]
|
[STORAGE]
|
||||||
playlist_path = /playlists
|
path = /media
|
||||||
clips_root = /media
|
|
||||||
filler_path = /media/filler/filler-clips
|
filler_path = /media/filler/filler-clips
|
||||||
filler_clip = /media/filler/filler.mp4
|
filler_clip = /media/filler/filler.mp4
|
||||||
blackclip = /opt/dummy.mp4
|
blackclip = /media/dummy.mp4
|
||||||
day_start = 05:59:25.000
|
|
||||||
|
|
||||||
|
|
||||||
# play ordered or ramdomly files from clips_root
|
|
||||||
# extensions can be a list
|
|
||||||
# set shuffle to True to pick files randomly
|
|
||||||
[FOLDER]
|
|
||||||
storage = /media
|
|
||||||
extensions = ["*.mp4"]
|
extensions = ["*.mp4"]
|
||||||
shuffle = False
|
shuffle = False
|
||||||
|
|
||||||
@ -111,7 +110,7 @@ shuffle = False
|
|||||||
# on windows fontfile path need to be like this: C\:/WINDOWS/fonts/DejaVuSans.ttf
|
# on windows fontfile path need to be like this: C\:/WINDOWS/fonts/DejaVuSans.ttf
|
||||||
# textfile has the same pattern
|
# textfile has the same pattern
|
||||||
[TEXT]
|
[TEXT]
|
||||||
textfile = /opt/live.txt
|
textfile = /media/live.txt
|
||||||
fontsize = 24
|
fontsize = 24
|
||||||
fontcolor = white
|
fontcolor = white
|
||||||
fontfile = /usr/share/fonts/truetype/dejavu/DejaVuSans.ttf
|
fontfile = /usr/share/fonts/truetype/dejavu/DejaVuSans.ttf
|
||||||
@ -134,7 +133,7 @@ post_comp_video = [
|
|||||||
"-maxrate", "1300k", "-bufsize", "2600k", "-preset", "medium", "-profile:v", "Main",
|
"-maxrate", "1300k", "-bufsize", "2600k", "-preset", "medium", "-profile:v", "Main",
|
||||||
"-level", "3.1"
|
"-level", "3.1"
|
||||||
]
|
]
|
||||||
post_comp_audio = ["-c:a", "libfdk_aac", "-ar", "44100", "-b:a", "128k"]
|
post_comp_audio = ["-c:a", "aac", "-ar", "44100", "-b:a", "128k"]
|
||||||
post_comp_extra = ["-flags", "+global_header", "-f", "flv"]
|
post_comp_extra = ["-flags", "+global_header", "-f", "flv"]
|
||||||
post_comp_copy = ["-bsf:a", "aac_adtstoasc"]
|
post_comp_copy = ["-bsf:a", "aac_adtstoasc"]
|
||||||
out_addr = rtmp://127.0.0.1/live/stream
|
out_addr = rtmp://127.0.0.1/live/stream
|
||||||
|
48
ffplayout.py
48
ffplayout.py
@ -55,8 +55,7 @@ else:
|
|||||||
|
|
||||||
_general = SimpleNamespace(
|
_general = SimpleNamespace(
|
||||||
stop=cfg.getboolean('GENERAL', 'stop_on_error'),
|
stop=cfg.getboolean('GENERAL', 'stop_on_error'),
|
||||||
threshold=cfg.getfloat('GENERAL', 'stop_threshold'),
|
threshold=cfg.getfloat('GENERAL', 'stop_threshold')
|
||||||
playlist_mode=cfg.getboolean('GENERAL', 'playlist_mode')
|
|
||||||
)
|
)
|
||||||
|
|
||||||
_mail = SimpleNamespace(
|
_mail = SimpleNamespace(
|
||||||
@ -98,16 +97,17 @@ else:
|
|||||||
start_t = None
|
start_t = None
|
||||||
|
|
||||||
_playlist = SimpleNamespace(
|
_playlist = SimpleNamespace(
|
||||||
path=cfg.get('PLAYLIST', 'playlist_path'),
|
mode=cfg.getboolean('PLAYLIST', 'playlist_mode'),
|
||||||
start=start_t,
|
path=cfg.get('PLAYLIST', 'path'),
|
||||||
filler=cfg.get('PLAYLIST', 'filler_clip'),
|
start=start_t
|
||||||
blackclip=cfg.get('PLAYLIST', 'blackclip'),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
_folder = SimpleNamespace(
|
_storage = SimpleNamespace(
|
||||||
storage=cfg.get('FOLDER', 'storage'),
|
path=cfg.get('STORAGE', 'path'),
|
||||||
extensions=json.loads(cfg.get('FOLDER', 'extensions')),
|
filler=cfg.get('STORAGE', 'filler_clip'),
|
||||||
shuffle=cfg.getboolean('FOLDER', 'shuffle')
|
blackclip=cfg.get('STORAGE', 'blackclip'),
|
||||||
|
extensions=json.loads(cfg.get('STORAGE', 'extensions')),
|
||||||
|
shuffle=cfg.getboolean('STORAGE', 'shuffle')
|
||||||
)
|
)
|
||||||
|
|
||||||
_text = SimpleNamespace(
|
_text = SimpleNamespace(
|
||||||
@ -430,7 +430,7 @@ def set_length(duration, seek, out):
|
|||||||
# generate a dummy clip, with black color and empty audiotrack
|
# generate a dummy clip, with black color and empty audiotrack
|
||||||
def gen_dummy(duration):
|
def gen_dummy(duration):
|
||||||
if _pre_comp.copy:
|
if _pre_comp.copy:
|
||||||
return ['-i', _playlist.blackclip, '-t', str(duration)]
|
return ['-i', _storage.blackclip, '-t', str(duration)]
|
||||||
else:
|
else:
|
||||||
color = '#121212'
|
color = '#121212'
|
||||||
# TODO: add noise could be an config option
|
# TODO: add noise could be an config option
|
||||||
@ -447,7 +447,7 @@ def gen_dummy(duration):
|
|||||||
|
|
||||||
# when playlist is not 24 hours long, we generate a loop from filler clip
|
# when playlist is not 24 hours long, we generate a loop from filler clip
|
||||||
def gen_filler_loop(duration):
|
def gen_filler_loop(duration):
|
||||||
if not _playlist.filler:
|
if not _storage.filler:
|
||||||
# when no filler is set, generate a dummy
|
# when no filler is set, generate a dummy
|
||||||
logger.warning('No filler is set!')
|
logger.warning('No filler is set!')
|
||||||
return gen_dummy(duration)
|
return gen_dummy(duration)
|
||||||
@ -455,7 +455,7 @@ def gen_filler_loop(duration):
|
|||||||
# get duration from filler
|
# get duration from filler
|
||||||
cmd = [
|
cmd = [
|
||||||
'ffprobe', '-v', 'error', '-show_entries', 'format=duration',
|
'ffprobe', '-v', 'error', '-show_entries', 'format=duration',
|
||||||
'-of', 'default=noprint_wrappers=1:nokey=1', _playlist.filler]
|
'-of', 'default=noprint_wrappers=1:nokey=1', _storage.filler]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
f_dur = float(check_output(cmd).decode('utf-8'))
|
f_dur = float(check_output(cmd).decode('utf-8'))
|
||||||
@ -466,7 +466,7 @@ def gen_filler_loop(duration):
|
|||||||
if f_dur > duration:
|
if f_dur > duration:
|
||||||
# cut filler
|
# cut filler
|
||||||
logger.info('Generate filler with {} seconds'.format(duration))
|
logger.info('Generate filler with {} seconds'.format(duration))
|
||||||
return ['-i', _playlist.filler] + set_length(
|
return ['-i', _storage.filler] + set_length(
|
||||||
f_dur, 0, duration)
|
f_dur, 0, duration)
|
||||||
else:
|
else:
|
||||||
# loop filles n times
|
# loop filles n times
|
||||||
@ -474,7 +474,7 @@ def gen_filler_loop(duration):
|
|||||||
logger.info('Loop filler {} times, total duration: {}'.format(
|
logger.info('Loop filler {} times, total duration: {}'.format(
|
||||||
loop_count, duration))
|
loop_count, duration))
|
||||||
return ['-stream_loop', str(loop_count),
|
return ['-stream_loop', str(loop_count),
|
||||||
'-i', _playlist.filler, '-t', str(duration)]
|
'-i', _storage.filler, '-t', str(duration)]
|
||||||
else:
|
else:
|
||||||
logger.error("Can't get filler length, generate dummy!")
|
logger.error("Can't get filler length, generate dummy!")
|
||||||
return gen_dummy(duration)
|
return gen_dummy(duration)
|
||||||
@ -528,7 +528,7 @@ def gen_input(has_begin, src, begin, dur, seek, out, last):
|
|||||||
logger.info('we are under time, new_len is: {}'.format(new_len))
|
logger.info('we are under time, new_len is: {}'.format(new_len))
|
||||||
|
|
||||||
if time_diff >= ref_time:
|
if time_diff >= ref_time:
|
||||||
if src == _playlist.filler:
|
if src == _storage.filler:
|
||||||
# when filler is something like a clock,
|
# when filler is something like a clock,
|
||||||
# is better to start the clip later and to play until end
|
# is better to start the clip later and to play until end
|
||||||
src_cmd = src_or_dummy(src, dur, dur - new_len, dur)
|
src_cmd = src_or_dummy(src, dur, dur - new_len, dur)
|
||||||
@ -551,7 +551,7 @@ def gen_input(has_begin, src, begin, dur, seek, out, last):
|
|||||||
logger.info('we are over time, new_len is: {}'.format(new_len))
|
logger.info('we are over time, new_len is: {}'.format(new_len))
|
||||||
|
|
||||||
if new_len > 5.0:
|
if new_len > 5.0:
|
||||||
if src == _playlist.filler:
|
if src == _storage.filler:
|
||||||
src_cmd = src_or_dummy(src, dur, out - new_len, out)
|
src_cmd = src_or_dummy(src, dur, out - new_len, out)
|
||||||
else:
|
else:
|
||||||
src_cmd = src_or_dummy(src, dur, seek, new_len)
|
src_cmd = src_or_dummy(src, dur, seek, new_len)
|
||||||
@ -933,7 +933,7 @@ class GetSourceIter(object):
|
|||||||
if filler:
|
if filler:
|
||||||
self.src_cmd = gen_filler_loop(self.out - self.seek)
|
self.src_cmd = gen_filler_loop(self.out - self.seek)
|
||||||
|
|
||||||
if _playlist.filler:
|
if _storage.filler:
|
||||||
self.is_dummy = False
|
self.is_dummy = False
|
||||||
self.duration += 1
|
self.duration += 1
|
||||||
else:
|
else:
|
||||||
@ -1104,16 +1104,16 @@ def main():
|
|||||||
stdin=PIPE
|
stdin=PIPE
|
||||||
)
|
)
|
||||||
|
|
||||||
if _general.playlist_mode:
|
if _playlist.mode:
|
||||||
watcher = None
|
watcher = None
|
||||||
get_source = GetSourceIter(encoder)
|
get_source = GetSourceIter(encoder)
|
||||||
else:
|
else:
|
||||||
logger.info("start folder mode")
|
logger.info("start folder mode")
|
||||||
media = MediaStore(_folder.extensions)
|
media = MediaStore(_storage.extensions)
|
||||||
media.fill(_folder.storage)
|
media.fill(_storage.path)
|
||||||
|
|
||||||
watcher = MediaWatcher(_folder.storage, _folder.extensions, media)
|
watcher = MediaWatcher(_storage.path, _storage.extensions, media)
|
||||||
get_source = GetSource(media, _folder.shuffle)
|
get_source = GetSource(media, _storage.shuffle)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
for src_cmd in get_source.next():
|
for src_cmd in get_source.next():
|
||||||
@ -1151,7 +1151,7 @@ def main():
|
|||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
if not _general.playlist_mode:
|
if not _playlist.mode:
|
||||||
from watchdog.events import PatternMatchingEventHandler
|
from watchdog.events import PatternMatchingEventHandler
|
||||||
from watchdog.observers import Observer
|
from watchdog.observers import Observer
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user