remove copy mode, #29
This commit is contained in:
parent
2ee3934dac
commit
af0906988e
@ -20,7 +20,6 @@ Features
|
||||
- trim and fade the last clip, to get full 24 hours
|
||||
- when playlist is not 24 hours long, loop filler clip until time is full
|
||||
- set custom day start, so you can have playlist for example: from 6am to 6am, instate of 0am to 12pm
|
||||
- copy mode, for more info's take a look in the [Wiki](https://github.com/ffplayout/ffplayout-engine/wiki/Copy-Mode)
|
||||
- normal system requirements and no special tools
|
||||
- no GPU power is needed
|
||||
- stream to server or play on desktop
|
||||
|
@ -56,7 +56,6 @@ log_level = INFO
|
||||
; output settings for the pre-compression
|
||||
; all clips get prepared in that way,
|
||||
; so the input for the final compression is unique
|
||||
; copy_mode means that there is no recomression
|
||||
; aspect mus be a float number
|
||||
; logo is only used if the path exist
|
||||
; with logo_opacity logo can make transparent
|
||||
@ -64,7 +63,6 @@ log_level = INFO
|
||||
; live_protocols is for checking input, is input a live source ffplayout handles it a bit different
|
||||
; info: outout is progressive!
|
||||
[PRE_COMPRESS]
|
||||
copy_mode = False
|
||||
width = 1024
|
||||
height = 576
|
||||
aspect = 1.778
|
||||
@ -94,13 +92,11 @@ day_start = 05:59:25.000
|
||||
; set shuffle to True to pick files randomly
|
||||
; 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
|
||||
; blackclip is for stream copy mode,
|
||||
; best for this is a ~4 hours clip with black color and soft noise sound
|
||||
[STORAGE]
|
||||
path = /media
|
||||
filler_path = /media/filler/filler-clips
|
||||
filler_clip = /media/filler/filler.mp4
|
||||
blackclip = /media/dummy.mp4
|
||||
extensions = ["*.mp4"]
|
||||
shuffle = False
|
||||
|
||||
@ -133,5 +129,4 @@ service_provider = example.org
|
||||
post_comp_video = ["-c:v", "libx264", "-crf", "23", "-x264-params", "keyint=50:min-keyint=25:scenecut=-1", "-maxrate", "1300k", "-bufsize", "2600k", "-preset", "medium", "-profile:v", "Main", "-level", "3.1"]
|
||||
post_comp_audio = ["-c:a", "aac", "-ar", "44100", "-b:a", "128k"]
|
||||
post_comp_extra = ["-flags", "+global_header", "-f", "flv"]
|
||||
post_comp_copy = ["-bsf:a", "aac_adtstoasc"]
|
||||
out_addr = rtmp://127.0.0.1/live/stream
|
||||
|
124
ffplayout.py
124
ffplayout.py
@ -106,7 +106,6 @@ _log = SimpleNamespace(
|
||||
)
|
||||
|
||||
_pre_comp = SimpleNamespace(
|
||||
copy=cfg.getboolean('PRE_COMPRESS', 'copy_mode'),
|
||||
w=cfg.getint('PRE_COMPRESS', 'width'),
|
||||
h=cfg.getint('PRE_COMPRESS', 'height'),
|
||||
aspect=cfg.getfloat('PRE_COMPRESS', 'aspect'),
|
||||
@ -135,7 +134,6 @@ _playlist = SimpleNamespace(
|
||||
_storage = SimpleNamespace(
|
||||
path=cfg.get('STORAGE', 'path'),
|
||||
filler=cfg.get('STORAGE', 'filler_clip'),
|
||||
blackclip=cfg.get('STORAGE', 'blackclip'),
|
||||
extensions=json.loads(cfg.get('STORAGE', 'extensions')),
|
||||
shuffle=cfg.getboolean('STORAGE', 'shuffle')
|
||||
)
|
||||
@ -159,8 +157,7 @@ _playout = SimpleNamespace(
|
||||
out_addr=cfg.get('OUT', 'out_addr'),
|
||||
post_comp_video=json.loads(cfg.get('OUT', 'post_comp_video')),
|
||||
post_comp_audio=json.loads(cfg.get('OUT', 'post_comp_audio')),
|
||||
post_comp_extra=json.loads(cfg.get('OUT', 'post_comp_extra')),
|
||||
post_comp_copy=json.loads(cfg.get('OUT', 'post_comp_copy'))
|
||||
post_comp_extra=json.loads(cfg.get('OUT', 'post_comp_extra'))
|
||||
)
|
||||
|
||||
|
||||
@ -479,20 +476,17 @@ def set_length(duration, seek, out):
|
||||
|
||||
# generate a dummy clip, with black color and empty audiotrack
|
||||
def gen_dummy(duration):
|
||||
if _pre_comp.copy:
|
||||
return ['-i', _storage.blackclip, '-t', str(duration)]
|
||||
else:
|
||||
color = '#121212'
|
||||
# TODO: add noise could be an config option
|
||||
# noise = 'noise=alls=50:allf=t+u,hue=s=0'
|
||||
return [
|
||||
'-f', 'lavfi', '-i',
|
||||
'color=c={}:s={}x{}:d={}:r={},format=pix_fmts=yuv420p'.format(
|
||||
color, _pre_comp.w, _pre_comp.h, duration, _pre_comp.fps
|
||||
),
|
||||
'-f', 'lavfi', '-i', 'anoisesrc=d={}:c=pink:r=48000:a=0.05'.format(
|
||||
duration)
|
||||
]
|
||||
color = '#121212'
|
||||
# TODO: add noise could be an config option
|
||||
# noise = 'noise=alls=50:allf=t+u,hue=s=0'
|
||||
return [
|
||||
'-f', 'lavfi', '-i',
|
||||
'color=c={}:s={}x{}:d={}:r={},format=pix_fmts=yuv420p'.format(
|
||||
color, _pre_comp.w, _pre_comp.h, duration, _pre_comp.fps
|
||||
),
|
||||
'-f', 'lavfi', '-i', 'anoisesrc=d={}:c=pink:r=48000:a=0.05'.format(
|
||||
duration)
|
||||
]
|
||||
|
||||
|
||||
# when playlist is not 24 hours long, we generate a loop from filler clip
|
||||
@ -774,9 +768,6 @@ def build_filtergraph(first, duration, seek, out, ad, ad_last, ad_next, dummy,
|
||||
"""
|
||||
build final filter graph, with video and audio chain
|
||||
"""
|
||||
if _pre_comp.copy:
|
||||
return []
|
||||
|
||||
video_chain = []
|
||||
audio_chain = []
|
||||
video_map = ['-map', '[logo]']
|
||||
@ -866,17 +857,18 @@ class MediaWatcher:
|
||||
watch given folder for file changes and update media list
|
||||
"""
|
||||
|
||||
def __init__(self, path, extensions, media):
|
||||
self._path = path
|
||||
def __init__(self, media):
|
||||
self._media = media
|
||||
|
||||
self.event_handler = PatternMatchingEventHandler(patterns=extensions)
|
||||
self.event_handler = PatternMatchingEventHandler(
|
||||
patterns=_storage.extensions)
|
||||
self.event_handler.on_created = self.on_created
|
||||
self.event_handler.on_moved = self.on_moved
|
||||
self.event_handler.on_deleted = self.on_deleted
|
||||
|
||||
self.observer = Observer()
|
||||
self.observer.schedule(self.event_handler, self._path, recursive=True)
|
||||
self.observer.schedule(self.event_handler, self._media.folder,
|
||||
recursive=True)
|
||||
|
||||
self.observer.start()
|
||||
|
||||
@ -913,9 +905,8 @@ class GetSource:
|
||||
give next clip, depending on shuffle mode
|
||||
"""
|
||||
|
||||
def __init__(self, media, shuffle):
|
||||
def __init__(self, media):
|
||||
self._media = media
|
||||
self._shuffle = shuffle
|
||||
|
||||
self.last_played = []
|
||||
self.index = 0
|
||||
@ -923,7 +914,7 @@ class GetSource:
|
||||
|
||||
def next(self):
|
||||
while True:
|
||||
if self._shuffle:
|
||||
if _storage.shuffle:
|
||||
clip = random.choice(self._media.store)
|
||||
|
||||
if len(self.last_played) > len(self._media.store) / 2:
|
||||
@ -1273,63 +1264,44 @@ def main():
|
||||
year = get_date(False).split('-')[0]
|
||||
overlay = []
|
||||
|
||||
if _pre_comp.copy:
|
||||
ff_pre_settings = ["-c", "copy", "-f", "mpegts", "-"]
|
||||
else:
|
||||
ff_pre_settings = [
|
||||
'-pix_fmt', 'yuv420p', '-r', str(_pre_comp.fps),
|
||||
'-c:v', 'mpeg2video', '-intra',
|
||||
'-b:v', '{}k'.format(_pre_comp.v_bitrate),
|
||||
'-minrate', '{}k'.format(_pre_comp.v_bitrate),
|
||||
'-maxrate', '{}k'.format(_pre_comp.v_bitrate),
|
||||
'-bufsize', '{}k'.format(_pre_comp.v_bufsize),
|
||||
'-c:a', 's302m', '-strict', '-2',
|
||||
'-ar', '48000', '-ac', '2',
|
||||
'-f', 'mpegts', '-']
|
||||
ff_pre_settings = [
|
||||
'-pix_fmt', 'yuv420p', '-r', str(_pre_comp.fps),
|
||||
'-c:v', 'mpeg2video', '-intra',
|
||||
'-b:v', '{}k'.format(_pre_comp.v_bitrate),
|
||||
'-minrate', '{}k'.format(_pre_comp.v_bitrate),
|
||||
'-maxrate', '{}k'.format(_pre_comp.v_bitrate),
|
||||
'-bufsize', '{}k'.format(_pre_comp.v_bufsize),
|
||||
'-c:a', 's302m', '-strict', '-2',
|
||||
'-ar', '48000', '-ac', '2',
|
||||
'-f', 'mpegts', '-']
|
||||
|
||||
if os.path.isfile(_text.textfile):
|
||||
logger.info('Overlay text file: "{}"'.format(_text.textfile))
|
||||
overlay = [
|
||||
'-vf', ("drawtext=box={}:boxcolor='{}':boxborderw={}"
|
||||
":fontsize={}:fontcolor={}:fontfile='{}':textfile={}"
|
||||
":reload=1:x='{}':y='{}'").format(
|
||||
_text.box, _text.boxcolor, _text.boxborderw,
|
||||
_text.fontsize, _text.fontcolor, _text.fontfile,
|
||||
_text.textfile, _text.x, _text.y)
|
||||
]
|
||||
if os.path.isfile(_text.textfile):
|
||||
logger.info('Overlay text file: "{}"'.format(_text.textfile))
|
||||
overlay = [
|
||||
'-vf', ("drawtext=box={}:boxcolor='{}':boxborderw={}"
|
||||
":fontsize={}:fontcolor={}:fontfile='{}':textfile={}"
|
||||
":reload=1:x='{}':y='{}'").format(
|
||||
_text.box, _text.boxcolor, _text.boxborderw,
|
||||
_text.fontsize, _text.fontcolor, _text.fontfile,
|
||||
_text.textfile, _text.x, _text.y)
|
||||
]
|
||||
|
||||
try:
|
||||
if _playout.preview:
|
||||
# preview playout to player
|
||||
encoder = Popen([
|
||||
'ffplay', '-hide_banner', '-nostats', '-i', 'pipe:0'
|
||||
] + overlay,
|
||||
stderr=None, stdin=PIPE, stdout=None
|
||||
)
|
||||
] + overlay, stderr=None, stdin=PIPE, stdout=None)
|
||||
else:
|
||||
# playout to rtmp
|
||||
if _pre_comp.copy:
|
||||
encoder_cmd = [
|
||||
'ffmpeg', '-v', 'info', '-hide_banner', '-nostats',
|
||||
'-re', '-thread_queue_size', '256',
|
||||
'-i', 'pipe:0', '-c', 'copy'
|
||||
] + _playout.post_comp_copy
|
||||
else:
|
||||
encoder_cmd = [
|
||||
'ffmpeg', '-v', 'info', '-hide_banner', '-nostats',
|
||||
'-re', '-thread_queue_size', '256',
|
||||
'-i', 'pipe:0'
|
||||
] + overlay + _playout.post_comp_video \
|
||||
+ _playout.post_comp_audio
|
||||
|
||||
encoder = Popen(
|
||||
encoder_cmd + [
|
||||
encoder = Popen([
|
||||
'ffmpeg', '-v', 'info', '-hide_banner', '-nostats',
|
||||
'-re', '-thread_queue_size', '256',
|
||||
'-i', 'pipe:0'] + overlay + _playout.post_comp_video
|
||||
+ _playout.post_comp_audio + [
|
||||
'-metadata', 'service_name=' + _playout.name,
|
||||
'-metadata', 'service_provider=' + _playout.provider,
|
||||
'-metadata', 'year={}'.format(year)
|
||||
] + _playout.post_comp_extra + [_playout.out_addr],
|
||||
stdin=PIPE
|
||||
)
|
||||
] + _playout.post_comp_extra + [_playout.out_addr], stdin=PIPE)
|
||||
|
||||
if _playlist.mode and not stdin_args.folder:
|
||||
watcher = None
|
||||
@ -1337,8 +1309,8 @@ def main():
|
||||
else:
|
||||
logger.info("start folder mode")
|
||||
media = MediaStore()
|
||||
watcher = MediaWatcher(media.folder, _storage.extensions, media)
|
||||
get_source = GetSource(media, _storage.shuffle)
|
||||
watcher = MediaWatcher(media)
|
||||
get_source = GetSource(media)
|
||||
|
||||
try:
|
||||
for src_cmd in get_source.next():
|
||||
|
Loading…
Reference in New Issue
Block a user