UPDATE: VoD Thumbnails now take a screenshot from exactly halfway through the stream, instead of the beginning
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
from celery import Celery, shared_task, Task
|
from celery import Celery, shared_task, Task
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from celery_tasks.preferences import user_preferences
|
from celery_tasks.preferences import user_preferences
|
||||||
from utils.stream_utils import generate_thumbnail, get_streamer_live_status, get_custom_thumbnail_status, remove_hls_files
|
from utils.stream_utils import generate_thumbnail, get_streamer_live_status, get_custom_thumbnail_status, remove_hls_files, get_video_duration
|
||||||
from time import sleep
|
from time import sleep
|
||||||
from os import listdir, remove
|
from os import listdir, remove
|
||||||
from utils.path_manager import PathManager
|
from utils.path_manager import PathManager
|
||||||
@@ -10,7 +10,7 @@ import subprocess
|
|||||||
path_manager = PathManager()
|
path_manager = PathManager()
|
||||||
|
|
||||||
@shared_task
|
@shared_task
|
||||||
def update_thumbnail(user_id, stream_file, thumbnail_file, sleep_time) -> None:
|
def update_thumbnail(user_id, stream_file, thumbnail_file, sleep_time, second_capture=0) -> None:
|
||||||
"""
|
"""
|
||||||
Updates the thumbnail of a stream periodically
|
Updates the thumbnail of a stream periodically
|
||||||
"""
|
"""
|
||||||
@@ -19,7 +19,7 @@ def update_thumbnail(user_id, stream_file, thumbnail_file, sleep_time) -> None:
|
|||||||
if get_streamer_live_status(user_id)['is_live'] and not get_custom_thumbnail_status(user_id)['custom_thumbnail']:
|
if get_streamer_live_status(user_id)['is_live'] and not get_custom_thumbnail_status(user_id)['custom_thumbnail']:
|
||||||
print("Updating thumbnail...")
|
print("Updating thumbnail...")
|
||||||
generate_thumbnail(stream_file, thumbnail_file)
|
generate_thumbnail(stream_file, thumbnail_file)
|
||||||
update_thumbnail.apply_async((user_id, stream_file, thumbnail_file, sleep_time), countdown=sleep_time)
|
update_thumbnail.apply_async((user_id, stream_file, thumbnail_file, sleep_time, second_capture), countdown=sleep_time)
|
||||||
else:
|
else:
|
||||||
print(f"Stopping thumbnail updates for stream of {user_id}")
|
print(f"Stopping thumbnail updates for stream of {user_id}")
|
||||||
|
|
||||||
@@ -28,6 +28,8 @@ def combine_ts_stream(stream_path, vods_path, vod_file_name, thumbnail_file) ->
|
|||||||
"""
|
"""
|
||||||
Combines all ts files into a single vod, and removes the ts files
|
Combines all ts files into a single vod, and removes the ts files
|
||||||
"""
|
"""
|
||||||
|
vod_file_path = f"{vods_path}/{vod_file_name}.mp4"
|
||||||
|
|
||||||
ts_files = [f for f in listdir(stream_path) if f.endswith(".ts")]
|
ts_files = [f for f in listdir(stream_path) if f.endswith(".ts")]
|
||||||
ts_files.sort()
|
ts_files.sort()
|
||||||
|
|
||||||
@@ -48,7 +50,7 @@ def combine_ts_stream(stream_path, vods_path, vod_file_name, thumbnail_file) ->
|
|||||||
f"{stream_path}/list.txt",
|
f"{stream_path}/list.txt",
|
||||||
"-c",
|
"-c",
|
||||||
"copy",
|
"copy",
|
||||||
f"{vods_path}/{vod_file_name}.mp4"
|
vod_file_path
|
||||||
]
|
]
|
||||||
|
|
||||||
subprocess.run(vod_command)
|
subprocess.run(vod_command)
|
||||||
@@ -56,8 +58,12 @@ def combine_ts_stream(stream_path, vods_path, vod_file_name, thumbnail_file) ->
|
|||||||
# Remove HLS files, even if user is not streaming
|
# Remove HLS files, even if user is not streaming
|
||||||
remove_hls_files(stream_path)
|
remove_hls_files(stream_path)
|
||||||
|
|
||||||
|
# Get video duration and choose middle frame as thumbnail
|
||||||
|
video_duration = get_video_duration(vod_file_path)
|
||||||
|
second_capture = video_duration // 2
|
||||||
|
|
||||||
# Generate thumbnail for vod
|
# Generate thumbnail for vod
|
||||||
generate_thumbnail(f"{vods_path}/{vod_file_name}.mp4", thumbnail_file)
|
generate_thumbnail(vod_file_path, thumbnail_file, second_capture)
|
||||||
|
|
||||||
@shared_task
|
@shared_task
|
||||||
def convert_image_to_png(image_path, png_path):
|
def convert_image_to_png(image_path, png_path):
|
||||||
|
|||||||
@@ -172,7 +172,7 @@ def get_user_vods(user_id: int):
|
|||||||
vods = db.fetchall("""SELECT vods.*, username, category_name FROM vods JOIN users ON vods.user_id = users.user_id JOIN categories ON vods.category_id = categories.category_id WHERE vods.user_id = ? ORDER BY vod_id DESC;""", (user_id,))
|
vods = db.fetchall("""SELECT vods.*, username, category_name FROM vods JOIN users ON vods.user_id = users.user_id JOIN categories ON vods.category_id = categories.category_id WHERE vods.user_id = ? ORDER BY vod_id DESC;""", (user_id,))
|
||||||
return vods
|
return vods
|
||||||
|
|
||||||
def generate_thumbnail(stream_file: str, thumbnail_file: str) -> None:
|
def generate_thumbnail(stream_file: str, thumbnail_file: str, second_capture) -> None:
|
||||||
"""
|
"""
|
||||||
Generates the thumbnail of a stream
|
Generates the thumbnail of a stream
|
||||||
"""
|
"""
|
||||||
@@ -180,6 +180,8 @@ def generate_thumbnail(stream_file: str, thumbnail_file: str) -> None:
|
|||||||
thumbnail_command = [
|
thumbnail_command = [
|
||||||
"ffmpeg",
|
"ffmpeg",
|
||||||
"-y",
|
"-y",
|
||||||
|
"-ss",
|
||||||
|
f"{second_capture}",
|
||||||
"-i",
|
"-i",
|
||||||
f"{stream_file}",
|
f"{stream_file}",
|
||||||
"-vframes",
|
"-vframes",
|
||||||
@@ -203,6 +205,29 @@ def remove_hls_files(stream_path: str) -> None:
|
|||||||
if file.endswith(".ts") or file.endswith(".m3u8"):
|
if file.endswith(".ts") or file.endswith(".m3u8"):
|
||||||
os.remove(os.path.join(stream_path, file))
|
os.remove(os.path.join(stream_path, file))
|
||||||
|
|
||||||
|
def get_video_duration(video_path: str) -> int:
|
||||||
|
"""
|
||||||
|
Returns the length of a video in seconds
|
||||||
|
"""
|
||||||
|
video_length_command = [
|
||||||
|
"ffprobe",
|
||||||
|
"-v",
|
||||||
|
"error",
|
||||||
|
"-show_entries",
|
||||||
|
"format=duration",
|
||||||
|
"-of",
|
||||||
|
"default=noprint_wrappers=1:nokey=1",
|
||||||
|
video_path
|
||||||
|
]
|
||||||
|
|
||||||
|
try:
|
||||||
|
video_length = subprocess.check_output(video_length_command).decode("utf-8")
|
||||||
|
print(f"Video length: {video_length}")
|
||||||
|
return int(float(video_length))
|
||||||
|
except subprocess.CalledProcessError as e:
|
||||||
|
print(f"Error getting video length: {e}")
|
||||||
|
return 0
|
||||||
|
|
||||||
def get_stream_tags(user_id: int) -> Optional[List[str]]:
|
def get_stream_tags(user_id: int) -> Optional[List[str]]:
|
||||||
"""
|
"""
|
||||||
Given a stream return tags associated with the user's stream
|
Given a stream return tags associated with the user's stream
|
||||||
|
|||||||
Reference in New Issue
Block a user