commit
085ff865bb
3
.github/FUNDING.yml
vendored
Normal file
3
.github/FUNDING.yml
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: [jb-alvarado]
|
@ -16,7 +16,7 @@ Features
|
||||
- playing clips from [watched folder](https://github.com/ffplayout/ffplayout-engine/wiki/Watch-Folder)
|
||||
- send emails with error message
|
||||
- overlay a logo
|
||||
- overlay scrolling text
|
||||
- overlay text, controllable through [messenger](https://github.com/ffplayout/messenger) over libzmq
|
||||
- **EBU R128 loudness** normalization (single pass) (experimental)
|
||||
- loop clip in playlist which `out` value is higher then its `duration`, see also [Loop Clip](https://github.com/ffplayout/ffplayout-engine/wiki/Loop-Clip)
|
||||
- loop playlist infinitely
|
||||
@ -31,7 +31,7 @@ Features
|
||||
- add filters to input, if is necessary to match output stream:
|
||||
- **yadif** (deinterlacing)
|
||||
- **pad** (letterbox or pillarbox to fit aspect)
|
||||
- **framerate** (change fps)
|
||||
- **fps** (change fps)
|
||||
- **scale** (fit target resolution)
|
||||
- **aevalsrc** (if video have no audio)
|
||||
- **apad** (add silence if audio duration is to short)
|
||||
@ -44,6 +44,7 @@ Requirements
|
||||
- python module **watchdog** (only when `playlist_mode = False`)
|
||||
- python module **colorama** if you are on windows
|
||||
- **ffmpeg v4.2+** and **ffprobe** (**ffplay** if you want to play on desktop)
|
||||
- if you want to overlay text, ffmpeg needs to have **libzmq**
|
||||
- RAM and CPU depends on video resolution, minimum 4 threads and 3GB RAM for 720p are recommend
|
||||
|
||||
JSON Playlist Example
|
||||
|
@ -110,23 +110,13 @@ extensions = ["*.mp4"]
|
||||
shuffle = False
|
||||
|
||||
|
||||
; overlay text
|
||||
; for paramters check ffmpeg doc
|
||||
; leave textfile blank when you don't need this
|
||||
; in some systems decimal point is a comma, have this in mind when ffmpeg complains about wrong values
|
||||
; overlay text in combination with messenger: https://github.com/ffplayout/messenger
|
||||
; on windows fontfile path need to be like this: C\:/WINDOWS/fonts/DejaVuSans.ttf
|
||||
; textfile has the same pattern
|
||||
; in a standard environment the filter drawtext node is: Parsed_drawtext_2
|
||||
[TEXT]
|
||||
add_text = True
|
||||
textfile = /media/live.txt
|
||||
fontsize = 24
|
||||
fontcolor = white
|
||||
bind_address = tcp://127.0.0.1:5555
|
||||
fontfile = /usr/share/fonts/truetype/dejavu/DejaVuSans.ttf
|
||||
box = 1
|
||||
boxcolor = black@0xbb
|
||||
boxborderw = 6
|
||||
x = w-w/8*mod(t,8*(w+tw)/w)
|
||||
y = (h-line_h)*0.9
|
||||
|
||||
|
||||
; the final playout post compression
|
||||
|
36
ffplayout.py
36
ffplayout.py
@ -212,15 +212,8 @@ def load_config():
|
||||
_storage.shuffle = cfg.getboolean('STORAGE', 'shuffle')
|
||||
|
||||
_text.add_text = cfg.getboolean('TEXT', 'add_text')
|
||||
_text.textfile = cfg.get('TEXT', 'textfile')
|
||||
_text.fontsize = cfg.get('TEXT', 'fontsize')
|
||||
_text.fontcolor = cfg.get('TEXT', 'fontcolor')
|
||||
_text.address = cfg.get('TEXT', 'bind_address')
|
||||
_text.fontfile = cfg.get('TEXT', 'fontfile')
|
||||
_text.box = cfg.get('TEXT', 'box')
|
||||
_text.boxcolor = cfg.get('TEXT', 'boxcolor')
|
||||
_text.boxborderw = cfg.get('TEXT', 'boxborderw')
|
||||
_text.x = cfg.get('TEXT', 'x')
|
||||
_text.y = cfg.get('TEXT', 'y')
|
||||
|
||||
if _init.load:
|
||||
_log.to_file = cfg.getboolean('LOGGING', 'log_to_file')
|
||||
@ -909,14 +902,21 @@ def handle_list_end(probe, new_length, src, begin, dur, seek, out):
|
||||
messenger.info(
|
||||
'We are over time, new length is: {0:.2f}'.format(new_length))
|
||||
|
||||
if dur > new_length > 1.5:
|
||||
missing_secs = abs(new_length - (dur - seek))
|
||||
|
||||
if dur > new_length > 1.5 and dur - seek >= new_length:
|
||||
src_cmd = src_or_dummy(probe, src, dur, seek, new_out)
|
||||
elif dur > new_length > 0.0:
|
||||
messenger.info(
|
||||
'Last clip less then 1.5 second long, skip:\n{}'.format(src))
|
||||
src_cmd = None
|
||||
|
||||
if missing_secs > 2:
|
||||
new_playlist = False
|
||||
messenger.error(
|
||||
'Reach playlist end,\n{0:.2f} seconds needed.'.format(
|
||||
missing_secs))
|
||||
else:
|
||||
missing_secs = abs(new_length - dur)
|
||||
new_out = out
|
||||
new_playlist = False
|
||||
src_cmd = src_or_dummy(probe, src, dur, seek, out)
|
||||
@ -1587,15 +1587,13 @@ def main():
|
||||
'-bufsize', '{}k'.format(_pre_comp.v_bufsize)
|
||||
] + pre_audio_codec() + ['-f', 'mpegts', '-']
|
||||
|
||||
if _text.add_text and os.path.isfile(_text.textfile):
|
||||
messenger.info('Overlay text file: "{}"'.format(_text.textfile))
|
||||
if _text.add_text:
|
||||
messenger.info('Using drawtext node, listening on address: {}'.format(
|
||||
_text.address
|
||||
))
|
||||
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)
|
||||
'-vf', "null,zmq=b='{}',drawtext=text='':fontfile='{}'".format(
|
||||
_text.address.replace(':', '\\:'), _text.fontfile)
|
||||
]
|
||||
|
||||
try:
|
||||
@ -1676,6 +1674,8 @@ def main():
|
||||
_ff.encoder.terminate()
|
||||
|
||||
finally:
|
||||
if _ff.encoder.poll() is None:
|
||||
_ff.encoder.terminate()
|
||||
_ff.encoder.wait()
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user