- stderr from both processes now displayed in console - streamlink checked for early exit before starting ffmpeg - RuntimeError shown to user if stream unavailable Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
78 lines
2.1 KiB
Python
78 lines
2.1 KiB
Python
import asyncio
|
|
import signal
|
|
|
|
from rich.console import Console
|
|
|
|
from config import load_config
|
|
from capture import capture_frames
|
|
from analyzer import VisionAnalyzer
|
|
from output import print_description, log_description
|
|
|
|
console = Console()
|
|
|
|
|
|
async def run(config) -> None:
|
|
analyzer = VisionAnalyzer(
|
|
api_key=config.gemini_api_key,
|
|
base_url=config.gemini_base_url,
|
|
lang=config.lang,
|
|
)
|
|
|
|
console.print(
|
|
f"[bold green]Starting stream analysis[/bold green] "
|
|
f"channel=[cyan]{config.channel}[/cyan] "
|
|
f"interval=[cyan]{config.interval}s[/cyan] "
|
|
f"quality=[cyan]{config.quality}[/cyan]"
|
|
)
|
|
console.print("[dim]Press Ctrl+C to stop[/dim]\n")
|
|
|
|
frame_number = 0
|
|
|
|
try:
|
|
async for frame_data in capture_frames(
|
|
config.channel, config.quality, config.interval
|
|
):
|
|
frame_number += 1
|
|
console.print(f"[dim]Captured frame #{frame_number}, analyzing...[/dim]")
|
|
|
|
try:
|
|
description = await analyzer.analyze_frame(frame_data)
|
|
except Exception as e:
|
|
console.print(f"[bold red]Analysis error:[/bold red] {e}")
|
|
continue
|
|
|
|
print_description(description, frame_number)
|
|
await log_description(config.log_file, description, frame_number)
|
|
except RuntimeError as e:
|
|
console.print(f"[bold red]Error:[/bold red] {e}")
|
|
finally:
|
|
if frame_number == 0:
|
|
console.print("[bold yellow]No frames were captured.[/bold yellow]")
|
|
|
|
|
|
def main() -> None:
|
|
config = load_config()
|
|
|
|
loop = asyncio.new_event_loop()
|
|
asyncio.set_event_loop(loop)
|
|
|
|
task = loop.create_task(run(config))
|
|
|
|
def shutdown(sig, frame):
|
|
console.print("\n[bold yellow]Shutting down...[/bold yellow]")
|
|
task.cancel()
|
|
|
|
signal.signal(signal.SIGINT, shutdown)
|
|
signal.signal(signal.SIGTERM, shutdown)
|
|
|
|
try:
|
|
loop.run_until_complete(task)
|
|
except asyncio.CancelledError:
|
|
console.print("[bold green]Stopped.[/bold green]")
|
|
finally:
|
|
loop.close()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|