restreamer: Don't offer a variant on the master playlist if it's outside requested time range

This prevents clients from picking a variant that they then can't play any content for.
In general we expect the same content to be available on all variants being captured,
but if the set of captured variants changes we still want to handle that gracefully.
pull/6/head
Mike Lang 6 years ago
parent 3bbe1ed32d
commit 8f5a98a906

@ -1,4 +1,5 @@
import datetime
import errno import errno
import functools import functools
import json import json
@ -85,6 +86,17 @@ def list_segments(stream, variant, hour):
return json.dumps(listdir(path, error=False)) return json.dumps(listdir(path, error=False))
def time_range_for_variant(stream, variant):
"""Returns earliest and latest times that the given variant has segments for
(up to hour resolution), or 404 if it doesn't exist / is empty."""
hours = listdir(os.path.join(app.static_folder, stream, variant))
if not hours:
abort(404)
first, last = min(hours), max(hours)
# note last hour parses to _start_ of that hour, so we add 1h to go to end of that hour
return dateutil.parser.parse(first), dateutil.parser.parse(last) + datetime.timedelta(hours=1)
@app.route('/playlist/<stream>.m3u8') @app.route('/playlist/<stream>.m3u8')
@has_path_args @has_path_args
def generate_master_playlist(stream): def generate_master_playlist(stream):
@ -93,11 +105,24 @@ def generate_master_playlist(stream):
start, end: The time to begin and end the stream at. start, end: The time to begin and end the stream at.
See generate_media_playlist for details. See generate_media_playlist for details.
""" """
start = dateutil.parser.parse(request.args['start']) if 'start' in request.args else None
end = dateutil.parser.parse(request.args['end']) if 'end' in request.args else None
variants = listdir(os.path.join(app.static_folder, stream)) variants = listdir(os.path.join(app.static_folder, stream))
playlists = {
variant: url_for('generate_media_playlist', stream=stream, variant=variant, **request.args) playlists = {}
for variant in variants for variant in variants:
} # If start or end are given, try to restrict offered variants to ones which exist for that
# time range.
if start is not None or end is not None:
first, last = time_range_for_variant(stream, variant)
if start is not None and last < start:
continue # last time for variant is before our start time, don't offer variant
if end is not None and end < first:
continue # our end time is before first time for variant, don't offer variant
playlists[variant] = url_for(
'generate_media_playlist', stream=stream, variant=variant, **request.args
)
return generate_hls.generate_master(playlists) return generate_hls.generate_master(playlists)

Loading…
Cancel
Save