Add video duration handling for chat rendering and merging

This commit is contained in:
MaddoScientisto 2026-02-10 08:04:08 +01:00
commit cdef8cf9bb
4 changed files with 126 additions and 19 deletions

View file

@ -48,7 +48,7 @@ from modules.config import ConfigManager
from modules.notifications import NotificationManager
from modules.utils import (
detect_operating_system, get_ffmpeg_executable, get_twitch_downloader_executable,
get_unique_filename, verify_streamlink, verify_ffmpeg, verify_twitch_downloader
get_unique_filename, get_video_duration, verify_streamlink, verify_ffmpeg, verify_twitch_downloader
)
from modules.stream_monitor import StreamMonitor
from modules.recorder import StreamRecorder
@ -410,7 +410,17 @@ class TwitchArchive:
if live_chat_downloaded:
chat_video_path = str(self.file_manager.chat_mp4_path / f"{PREFIX_CHAT}{filename_base}.mp4")
output_args = self.processor.build_chat_output_args()
chat_rendered_successfully = self.downloader.render_chat(chat_json_path, chat_video_path, output_args)
# Get video duration to trim chat accordingly
ffmpeg_path = get_ffmpeg_executable(self.os_type)
video_duration = get_video_duration(live_proc_path, ffmpeg_path)
chat_rendered_successfully = self.downloader.render_chat(
chat_json_path,
chat_video_path,
output_args,
video_duration=video_duration
)
# Merge video and chat if configured
merged_video_path = None
@ -488,7 +498,18 @@ class TwitchArchive:
if not live_chat_downloaded:
chat_video_path = str(self.file_manager.chat_mp4_path / f"{PREFIX_CHAT}{filename_base}.mp4")
output_args = self.processor.build_chat_output_args()
chat_rendered_successfully = self.downloader.download_and_render_chat(current_vod, chat_json_path, chat_video_path, output_args)
# Get VOD duration to trim chat accordingly
ffmpeg_path = get_ffmpeg_executable(self.os_type)
vod_duration = get_video_duration(vod_path, ffmpeg_path)
chat_rendered_successfully = self.downloader.download_and_render_chat(
current_vod,
chat_json_path,
chat_video_path,
output_args,
video_duration=vod_duration
)
# Merge VOD and chat if configured
if chat_rendered_successfully and self.mergeVideoChat and os.path.exists(vod_path) and os.path.exists(chat_video_path):
@ -867,14 +888,18 @@ class TwitchArchiveManager:
print(f'{Fore.MAGENTA}[DEBUG {username}] Stream data: {stream_data}{Style.RESET_ALL}')
if stream_data:
# Stream is live - check if it has required data
if stream_data.get('archiveVideo') and stream_data['archiveVideo'].get('id'):
# Stream is live - check if it has required basic data (title and start time)
if stream_data.get('title') and stream_data.get('createdAt'):
# Create composite stream ID like single-streamer mode
# This prevents duplicate recordings in the same session
stream_id = f"{stream_data['createdAt']} - {username} - {stream_data.get('title', 'Untitled')}"
if self.verbose:
print(f'{Fore.MAGENTA}[DEBUG {username}] VOD ID: {stream_data["archiveVideo"]["id"]}{Style.RESET_ALL}')
# Check if VOD ID is available (for live chat)
if stream_data.get('archiveVideo') and stream_data['archiveVideo'].get('id'):
print(f'{Fore.MAGENTA}[DEBUG {username}] VOD ID: {stream_data["archiveVideo"]["id"]}{Style.RESET_ALL}')
else:
print(f'{Fore.MAGENTA}[DEBUG {username}] No VOD ID available (VODs may be disabled){Style.RESET_ALL}')
print(f'{Fore.MAGENTA}[DEBUG {username}] Composite Stream ID: {stream_id}{Style.RESET_ALL}')
# Check if we're currently recording this stream
@ -890,6 +915,11 @@ class TwitchArchiveManager:
print(f'{Fore.CYAN}Title: {stream_data.get("title", "No title")}{Style.RESET_ALL}')
print(f'{Fore.CYAN}Started at: {stream_data["createdAt"]}{Style.RESET_ALL}')
# Warn if VOD ID not available
if not (stream_data.get('archiveVideo') and stream_data['archiveVideo'].get('id')):
print(f'{Fore.YELLOW}⚠ VOD ID not available - live chat download will be skipped{Style.RESET_ALL}')
print(f'{Fore.YELLOW} Stream recording will proceed normally{Style.RESET_ALL}')
# Mark as currently recording
self.active_recordings[username] = stream_id
@ -906,8 +936,8 @@ class TwitchArchiveManager:
if self.verbose:
print(f'{Fore.CYAN}[{username}] Currently recording this stream, skipping duplicate...{Style.RESET_ALL}')
else:
# Stream is live but VOD ID not available yet
print(f'{Fore.YELLOW}[{username}] Stream is live but VOD ID not ready yet (title: {stream_data.get("title", "No title")}){Style.RESET_ALL}')
# Stream is live but not fully initialized yet
print(f'{Fore.YELLOW}[{username}] Stream starting up, waiting for stream data...{Style.RESET_ALL}')
else:
# Not live
if self.verbose:
@ -1000,7 +1030,17 @@ class TwitchArchiveManager:
if live_chat_downloaded:
chat_video_path = str(archiver.file_manager.chat_mp4_path / f"{PREFIX_CHAT}{filename_base}.mp4")
output_args = archiver.processor.build_chat_output_args()
chat_rendered_successfully = archiver.downloader.render_chat(chat_json_path, chat_video_path, output_args)
# Get video duration to trim chat accordingly
ffmpeg_path = get_ffmpeg_executable(archiver.os_type)
video_duration = get_video_duration(live_proc_path, ffmpeg_path)
chat_rendered_successfully = archiver.downloader.render_chat(
chat_json_path,
chat_video_path,
output_args,
video_duration=video_duration
)
# Merge video and chat if configured
merged_video_path = None
@ -1081,7 +1121,18 @@ class TwitchArchiveManager:
if archiver.downloadCHAT and not live_chat_downloaded:
chat_video_path = str(archiver.file_manager.chat_mp4_path / f"{PREFIX_CHAT}{filename_base}.mp4")
output_args = archiver.processor.build_chat_output_args()
chat_rendered_successfully = archiver.downloader.download_and_render_chat(current_vod, chat_json_path, chat_video_path, output_args)
# Get VOD duration to trim chat accordingly
ffmpeg_path = get_ffmpeg_executable(archiver.os_type)
vod_duration = get_video_duration(vod_path, ffmpeg_path)
chat_rendered_successfully = archiver.downloader.download_and_render_chat(
current_vod,
chat_json_path,
chat_video_path,
output_args,
video_duration=vod_duration
)
# Merge VOD and chat if configured
if chat_rendered_successfully and archiver.mergeVideoChat and os.path.exists(vod_path) and os.path.exists(chat_video_path):