From 0f0aee36b3f001cda32a58fa34c59a246c0521e8 Mon Sep 17 00:00:00 2001 From: Mike Lang Date: Sat, 24 Sep 2022 19:12:55 +1000 Subject: [PATCH] restreamer: Add endpoint for previewing thumbnails --- restreamer/restreamer/main.py | 35 +++++++++++++++++++++++++++++++++++ restreamer/setup.py | 1 + 2 files changed, 36 insertions(+) diff --git a/restreamer/restreamer/main.py b/restreamer/restreamer/main.py index c64cc50..1e66e16 100644 --- a/restreamer/restreamer/main.py +++ b/restreamer/restreamer/main.py @@ -16,6 +16,7 @@ from gevent.pywsgi import WSGIServer from common import dateutil, get_best_segments, rough_cut_segments, fast_cut_segments, full_cut_segments, PromLogCountsHandler, install_stacksampler, serve_with_graceful_shutdown from common.flask_stats import request_stats, after_request +from common.images import compose_thumbnail_template from common.segments import feed_input, render_segments_waveform, extract_frame, list_segment_files from common.chat import get_batch_file_range, merge_messages @@ -394,6 +395,40 @@ def get_frame(channel, quality): return Response(extract_frame(segments, timestamp), mimetype='image/png') +@app.route('/thumbnail//.png') +@request_stats +@has_path_args +def get_thumbnail(channel, quality): + """ + Returns a PNG image which is a preview of how a thumbnail will be generated. + Params: + timestamp: Required. The frame to use as the thumbnail image. + Must be in ISO 8601 format (ie. yyyy-mm-ddTHH:MM:SS) and UTC. + template: Required. The template name to use. + Must be one of the template names (without file extension) as returned + by GET /files/thumbnail_templates + """ + template_name = request.args['template'] + template_path = os.path.join(app.static_folder, "thumbnail_templates", f"{template_name}.png") + if not os.path.exists(template_path): + return "No such template", 404 + + timestamp = dateutil.parse_utc_only(request.args['timestamp']) + + hours_path = os.path.join(app.static_folder, channel, quality) + if not os.path.isdir(hours_path): + abort(404) + + segments = get_best_segments(hours_path, timestamp, timestamp) + if not any(segment is not None for segment in segments): + return "We have no content available within the requested time range.", 406 + + frame = b''.join(extract_frame(segments, timestamp)) + template = compose_thumbnail_template(app.static_folder, template_name, frame) + + return Response(template, mimetype='image/png') + + @app.route('//chat.json') @request_stats @has_path_args diff --git a/restreamer/setup.py b/restreamer/setup.py index 9770ac9..0752e19 100644 --- a/restreamer/setup.py +++ b/restreamer/setup.py @@ -11,6 +11,7 @@ setup( "gevent", "monotonic", "prometheus-client", + "Pillow", # for thumbnail templates "wubloader-common", ], )