diff --git a/README.md b/README.md index ad017927..77ee3e51 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ Features - send emails with error message - overlay a logo - overlay scrolling text -- trim and fade the last clip, to get full 24 hours, if the duration is less then 6 seconds add a dummy clip +- trim and fade the last clip, to get full 24 hours - 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 @@ -38,7 +38,6 @@ JSON Playlist Example { "channel": "Test 1", "date": "2019-03-05", - "begin": "06:00:00.000", "length": "24:00:00.000", "program": [{ "in": 0, @@ -67,10 +66,10 @@ JSON Playlist Example } ``` -`"begin"` and `"length"` are optional, when you leave **begin** blank, length check will be ignored and the playlist starts from the begin, without time awareness. If you leave **length** blank, the validation will not check if the real length of the playlist will match the length value. +`"length"` are optional, when you leave **day_start** in config blank, length check will be ignored and the playlist starts from the begin, without time awareness. If you leave **length** blank, the validation will not check if the real length of the playlist will match the length value. #### Warning: -(Endless) streaming over multiple days will only work when the playlist have **both** keys and the **length** of the playlist is **24 hours**. If you need only some hours for every day, use a *cron* job, or something similar. +(Endless) streaming over multiple days will only work when config have **day_start** value and the **length** value of the playlist is **24 hours**. If you need only some hours for every day, use a *cron* job, or something similar. Source from URL / Live Stream ----- diff --git a/ffplayout.conf b/ffplayout.conf index 48ce8ca4..2ad8fcb8 100644 --- a/ffplayout.conf +++ b/ffplayout.conf @@ -78,24 +78,19 @@ ffmpeg_copy_settings = ["-c", "copy", "-bsf:v", "h264_mp4toannexb", "-f", "mpegt # "/playlists/2018/01" (/playlists/year/month) # strings in playlist must have ampersan (&) as: & -# day_start means at witch hour starts the day, as integer +# day_start means at which time the playlist should start +# leave day_start blank when playlist should always start at the begin # filler_path are for the GUI only at the moment # filler_clip get handle different, when a new length needs to calculate # blackclip is for stream copy mode, # best for this is a ~4 hours clip with black color and soft noise sound - -# time_shift adds or subtract seconds to the playlist start, -# this is usefull for example for hls, because it have a big delay -# the value will be added to the clip begin -# put 0 if you don't need it [PLAYLIST] playlist_path = /playlists clips_root = /media filler_path = /media/filler/filler-clips filler_clip = /media/filler/filler.mp4 blackclip = /opt/dummy.mp4 -day_start = 06:00:00.000 -time_shift = 35 +day_start = 05:59:25.000 # play ordered or ramdomly files from clips_root diff --git a/ffplayout.py b/ffplayout.py index d4eac862..8a274242 100755 --- a/ffplayout.py +++ b/ffplayout.py @@ -88,18 +88,20 @@ _pre_comp = SimpleNamespace( copy_settings=json.loads(cfg.get('PRE_COMPRESS', 'ffmpeg_copy_settings')) ) +stime = cfg.get('PLAYLIST', 'day_start').split(':') + +if stime[0] and stime[1] and stime[2]: + start_t = float(stime[0]) * 3600 + float(stime[1]) * 60 + float(stime[2]) +else: + start_t = None + _playlist = SimpleNamespace( path=cfg.get('PLAYLIST', 'playlist_path'), - t=cfg.get('PLAYLIST', 'day_start').split(':'), - start=0, + start=start_t, filler=cfg.get('PLAYLIST', 'filler_clip'), blackclip=cfg.get('PLAYLIST', 'blackclip'), - shift=cfg.getfloat('PLAYLIST', 'time_shift'), ) -_playlist.start = float(_playlist.t[0]) * 3600 + float(_playlist.t[1]) * 60 \ - + float(_playlist.t[2]) - _folder = SimpleNamespace( storage=cfg.get('FOLDER', 'storage'), extensions=json.loads(cfg.get('FOLDER', 'extensions')), @@ -261,7 +263,7 @@ def terminate_processes(decoder, encoder, watcher): def get_time(time_format): - t = datetime.today() + timedelta(seconds=_playlist.shift) + t = datetime.today() if time_format == 'hour': return t.hour elif time_format == 'full_sec': @@ -274,8 +276,8 @@ def get_time(time_format): def get_date(seek_day): - d = date.today() + timedelta(seconds=_playlist.shift) - if seek_day and get_time('full_sec') < _playlist.start: + d = date.today() + if _playlist.start and seek_day and get_time('full_sec') < _playlist.start: yesterday = d - timedelta(1) return yesterday.strftime('%Y-%m-%d') else: @@ -306,7 +308,8 @@ def check_sync(begin, encoder): time_now = get_time('full_sec') time_distance = begin - time_now - if 0 <= time_now < _playlist.start and not begin == _playlist.start: + if _playlist.start and 0 <= time_now < _playlist.start and \ + not begin == _playlist.start: time_distance -= 86400.0 # check that we are in tolerance time @@ -320,39 +323,28 @@ def check_sync(begin, encoder): # check begin and length -def check_start_and_length(json_nodes, counter): - # check start time and set begin - if 'begin' in json_nodes: - h, m, s = json_nodes["begin"].split(':') - if is_float(h) and is_float(m) and is_float(s): - begin = float(h) * 3600 + float(m) * 60 + float(s) - else: - begin = -100.0 - else: - begin = -100.0 +def check_start_and_length(json_nodes, total_play_time): + if _playlist.start: + # check if playlist is long enough + if 'length' in json_nodes: + l_h, l_m, l_s = json_nodes["length"].split(':') + if is_float(l_h) and is_float(l_m) and is_float(l_s): + length = float(l_h) * 3600 + float(l_m) * 60 + float(l_s) - # check if playlist is long enough - if 'length' in json_nodes: - l_h, l_m, l_s = json_nodes["length"].split(':') - if is_float(l_h) and is_float(l_m) and is_float(l_s): - length = float(l_h) * 3600 + float(l_m) * 60 + float(l_s) + if 'date' in json_nodes: + date = json_nodes["date"] + else: + date = get_date(True) - total_play_time = begin + counter - _playlist.start - - if 'date' in json_nodes: - date = json_nodes["date"] - else: - date = get_date(True) - - if total_play_time < length - 5: - mailer.error( - 'Playlist ({}) is not long enough!\n' - 'total play time is: {}'.format( - date, - timedelta(seconds=total_play_time)) - ) - logger.error('Playlist is only {} hours long!'.format( - timedelta(seconds=total_play_time))) + if total_play_time < length - 5: + mailer.error( + 'Playlist ({}) is not long enough!\n' + 'total play time is: {}'.format( + date, + timedelta(seconds=total_play_time)) + ) + logger.error('Playlist is only {} hours long!'.format( + timedelta(seconds=total_play_time))) # validate json values in new Thread @@ -473,11 +465,14 @@ def src_or_dummy(src, dur, seek, out): # return clip only if we are in 24 hours time range def gen_input(has_begin, src, begin, dur, seek, out, last): day_in_sec = 86400.0 - ref_time = day_in_sec + _playlist.start + ref_time = day_in_sec time = get_time('full_sec') - if 0 <= time < _playlist.start: - time += day_in_sec + if _playlist.start: + ref_time = day_in_sec + _playlist.start + + if 0 <= time < _playlist.start: + time += day_in_sec # calculate time difference to see if we are sync time_diff = out - seek + time @@ -721,7 +716,7 @@ class GetSourceIter(object): self._encoder = encoder self.last_time = get_time('full_sec') - if 0 <= self.last_time < _playlist.start: + if _playlist.start and 0 <= self.last_time < _playlist.start: self.last_time += 86400 self.last_mod_time = 0.0 @@ -770,12 +765,10 @@ class GetSourceIter(object): # and calculate the seek in time, for when the playlist comes back self.error_handling('Playlist not exist:') - # when begin is in playlist, get start time from it - if self.clip_nodes and 'begin' in self.clip_nodes: - h, m, s = self.clip_nodes["begin"].split(':') - if is_float(h) and is_float(m) and is_float(s): - self.has_begin = True - self.init_time = float(h) * 3600 + float(m) * 60 + float(s) + # when _playlist.start is set, use start time + if self.clip_nodes and _playlist.start: + self.has_begin = True + self.init_time = _playlist.start else: self.has_begin = False @@ -875,11 +868,14 @@ class GetSourceIter(object): self.ad = False day_in_sec = 86400.0 - ref_time = day_in_sec + _playlist.start + ref_time = day_in_sec time = get_time('full_sec') - if 0 <= time < _playlist.start: - time += day_in_sec + if _playlist.start: + ref_time = day_in_sec + _playlist.start + + if 0 <= time < _playlist.start: + time += day_in_sec time_diff = self.out - self.seek + time new_len = self.out - self.seek - (time_diff - ref_time)