loop filler clip, when playlist is not 24 hours long

This commit is contained in:
Jonathan Baecker 2019-07-19 14:58:28 +02:00
parent 457383ec83
commit 21a7b9e08d
2 changed files with 59 additions and 12 deletions

View File

@ -18,6 +18,7 @@ Features
- overlay a logo - overlay a logo
- overlay scrolling text - overlay scrolling text
- trim and fade the last clip, to get full 24 hours - 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 - 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) - 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 - normal system requirements and no special tools

View File

@ -23,6 +23,7 @@ import configparser
import glob import glob
import json import json
import logging import logging
import math
import os import os
import random import random
import smtplib import smtplib
@ -30,6 +31,7 @@ import signal
import socket import socket
import sys import sys
import time import time
from argparse import ArgumentParser from argparse import ArgumentParser
from datetime import date, datetime, timedelta from datetime import date, datetime, timedelta
from email.mime.multipart import MIMEMultipart from email.mime.multipart import MIMEMultipart
@ -441,6 +443,41 @@ def gen_dummy(duration):
] ]
# when playlist is not 24 hours long, we generate a loop from filler clip
def gen_filler_loop(duration):
if not _playlist.filler:
# when no filler is set, generate a dummy
logger.warning('No filler is set!')
return gen_dummy(duration)
else:
# get duration from filler
cmd = [
'ffprobe', '-v', 'error', '-show_entries', 'format=duration',
'-of', 'default=noprint_wrappers=1:nokey=1', _playlist.filler]
try:
f_dur = float(check_output(cmd).decode('utf-8'))
except (CalledProcessError, ValueError):
f_dur = None
if f_dur:
if f_dur > duration:
# cut filler
logger.info('Generate filler with {} seconds'.format(duration))
return ['-i', _playlist.filler] + set_length(
f_dur, 0, duration)
else:
# loop filles n times
loop_count = math.ceil(duration / f_dur)
logger.info('Loop filler {} times, total duration: {}'.format(
loop_count, duration))
return ['-stream_loop', str(loop_count),
'-i', _playlist.filler, '-t', str(duration)]
else:
logger.error("Can't get filler length, generate dummy!")
return gen_dummy(duration)
# when source path exist, generate input with seek and out time # when source path exist, generate input with seek and out time
# when path not exist, generate dummy clip # when path not exist, generate dummy clip
def src_or_dummy(src, dur, seek, out): def src_or_dummy(src, dur, seek, out):
@ -763,7 +800,7 @@ class GetSourceIter(object):
# when we have no playlist for the current day, # when we have no playlist for the current day,
# then we generate a black clip # then we generate a black clip
# and calculate the seek in time, for when the playlist comes back # and calculate the seek in time, for when the playlist comes back
self.error_handling('Playlist not exist:') self.eof_handling('Playlist not exist:', False)
# when _playlist.start is set, use start time # when _playlist.start is set, use start time
if self.clip_nodes and _playlist.start: if self.clip_nodes and _playlist.start:
@ -861,7 +898,7 @@ class GetSourceIter(object):
self.first, self.duration, self.seek, self.out, self.first, self.duration, self.seek, self.out,
self.ad, self.ad_last, self.ad_next, self.is_dummy) self.ad, self.ad_last, self.ad_next, self.is_dummy)
def error_handling(self, message): def eof_handling(self, message, filler):
self.seek = 0.0 self.seek = 0.0
self.out = 20 self.out = 20
self.duration = 20 self.duration = 20
@ -892,6 +929,13 @@ class GetSourceIter(object):
self.list_date = get_date(True) self.list_date = get_date(True)
self.last_time += self.out - self.seek self.last_time += self.out - self.seek
if filler:
self.src_cmd = gen_filler_loop(self.out - self.seek)
if _playlist.filler:
self.is_dummy = False
self.duration += 1
else:
self.src_cmd = gen_dummy(self.out - self.seek) self.src_cmd = gen_dummy(self.out - self.seek)
self.is_dummy = True self.is_dummy = True
self.set_filtergraph() self.set_filtergraph()
@ -966,7 +1010,8 @@ class GetSourceIter(object):
self.last_time = self.begin self.last_time = self.begin
self.out = self.time_left self.out = self.time_left
self.error_handling('Playlist is not valid!') self.eof_handling(
'Playlist is not long enough!', False)
else: else:
# when there is no time left and we are in time, # when there is no time left and we are in time,
@ -979,16 +1024,17 @@ class GetSourceIter(object):
self.begin += self.out - self.seek self.begin += self.out - self.seek
else: else:
if not _playlist.start or 'length' not in self.clip_nodes:
# when we reach currect end, stop script # when we reach currect end, stop script
if 'begin' not in self.clip_nodes or \
'length' not in self.clip_nodes and \
self.begin < get_time('full_sec'):
logger.info('Playlist reach End!') logger.info('Playlist reach End!')
return return
# when playlist exist but is empty, or not long enough, elif self.begin == self.init_time:
# generate dummy and send log # no clip was played, generate dummy
self.error_handling('Playlist is not valid!') self.eof_handling('Playlist is empty!', False)
else:
# playlist is not long enough, play filler
self.eof_handling('Playlist is not long enough!', True)
if self.src_cmd is not None: if self.src_cmd is not None:
yield self.src_cmd + self.filtergraph yield self.src_cmd + self.filtergraph