SYMBOL INDEX (117 symbols across 20 files) FILE: Backend/db.py class Base (line 13) | class Base(DeclarativeBase): function _database_url (line 17) | def _database_url() -> str: function init_db (line 39) | def init_db() -> None: FILE: Backend/gpt.py function _ollama_client (line 20) | def _ollama_client() -> Client: function _extract_model_name (line 24) | def _extract_model_name(model_obj) -> str: function list_ollama_models (line 34) | def list_ollama_models() -> Tuple[List[str], str]: function generate_response (line 67) | def generate_response(prompt: str, ai_model: str) -> str: function generate_script (line 142) | def generate_script( function get_search_terms (line 237) | def get_search_terms( function generate_metadata (line 315) | def generate_metadata( FILE: Backend/logstream.py class LogStream (line 7) | class LogStream: method __init__ (line 10) | def __init__(self, maxsize: int = 500): method clear (line 13) | def clear(self) -> None: method push (line 21) | def push(self, message: str, level: str = "info") -> None: method push_event (line 41) | def push_event(self, event_type: str, data: dict | None = None) -> None: method stream (line 60) | def stream(self, timeout: float = 30.0): function log (line 90) | def log(message: str, level: str = "info") -> None: FILE: Backend/main.py function models (line 27) | def models(): function generate (line 50) | def generate(): function get_job_status (line 68) | def get_job_status(job_id: str): function get_events (line 94) | def get_events(job_id: str): function cancel_job (line 124) | def cancel_job(job_id: str): function upload_songs (line 134) | def upload_songs(): function cancel_latest_running_job (line 159) | def cancel_latest_running_job(): FILE: Backend/models.py class Project (line 10) | class Project(Base): class GenerationJob (line 20) | class GenerationJob(Base): class GenerationEvent (line 61) | class GenerationEvent(Base): class Script (line 82) | class Script(Base): class Artifact (line 99) | class Artifact(Base): FILE: Backend/pipeline.py class PipelineCancelled (line 31) | class PipelineCancelled(Exception): function run_generation_pipeline (line 35) | def run_generation_pipeline( FILE: Backend/repository.py function utcnow (line 11) | def utcnow() -> datetime: function create_job (line 15) | def create_job(session: Session, payload: dict, max_attempts: int = 1) -... function append_event (line 31) | def append_event( function get_job (line 51) | def get_job(session: Session, job_id: str) -> Optional[GenerationJob]: function list_job_events (line 55) | def list_job_events( function request_cancel (line 72) | def request_cancel(session: Session, job_id: str) -> bool: function claim_next_queued_job (line 97) | def claim_next_queued_job(session: Session) -> Optional[GenerationJob]: function mark_completed (line 143) | def mark_completed(session: Session, job_id: str, result_path: str) -> N... function mark_cancelled (line 163) | def mark_cancelled( function mark_failed (line 176) | def mark_failed(session: Session, job_id: str, error_message: str) -> None: FILE: Backend/search.py function search_for_stock_videos (line 6) | def search_for_stock_videos(query: str, api_key: str, it: int, min_dur: ... FILE: Backend/tiktokvoice.py function split_string (line 79) | def split_string(string: str, chunk_size: int) -> List[str]: function get_api_response (line 98) | def get_api_response() -> requests.Response: function save_audio_file (line 105) | def save_audio_file(base64_data: str, filename: str = "output.mp3") -> N... function generate_audio (line 112) | def generate_audio(text: str, voice: str) -> bytes: function tts (line 121) | def tts( FILE: Backend/utils.py function clean_dir (line 25) | def clean_dir(path: str) -> None: function choose_random_song (line 53) | def choose_random_song() -> Optional[str]: function resolve_imagemagick_binary (line 82) | def resolve_imagemagick_binary() -> Optional[str]: function check_env_vars (line 113) | def check_env_vars() -> None: FILE: Backend/video.py function save_video (line 28) | def save_video(video_url: str, directory: str = str(TEMP_DIR)) -> str: function __generate_subtitles_assemblyai (line 49) | def __generate_subtitles_assemblyai(audio_path: str, voice: str) -> str: function __generate_subtitles_locally (line 81) | def __generate_subtitles_locally( function generate_subtitles (line 118) | def generate_subtitles( function combine_videos (line 162) | def combine_videos( function generate_video (line 268) | def generate_video( FILE: Backend/worker.py function _job_cancelled (line 21) | def _job_cancelled(job_id: str) -> bool: function _log_event (line 29) | def _log_event(job_id: str, message: str, level: str) -> None: function process_next_job (line 35) | def process_next_job() -> bool: function main (line 65) | def main() -> None: FILE: Backend/youtube.py function get_authenticated_service (line 67) | def get_authenticated_service(): function initialize_upload (line 93) | def initialize_upload(youtube: any, options: dict): function resumable_upload (line 133) | def resumable_upload(insert_request: MediaFileUpload): function upload_video (line 174) | def upload_video(video_path, title, description, category, keywords, pri... FILE: Frontend/app.js constant API_BASE_URL (line 22) | const API_BASE_URL = `${backendProtocol}//${backendHost}:8080`; constant API_FALLBACK_URL (line 23) | const API_FALLBACK_URL = `http://${backendHost}:8080`; function apiRequest (line 30) | async function apiRequest(path, options = {}) { function setModelOptions (line 52) | function setModelOptions(models, preferredModel) { function loadOllamaModels (line 69) | async function loadOllamaModels(reuseEnabled) { function showToast (line 110) | function showToast(message, type = "info") { function dismissToast (line 131) | function dismissToast(toast) { function updateColorDot (line 137) | function updateColorDot() { function formatTimestamp (line 152) | function formatTimestamp(ts) { function appendLogEntry (line 157) | function appendLogEntry(entry) { function pollJob (line 177) | async function pollJob() { function startJobPolling (line 224) | function startJobPolling(jobId) { function stopJobPolling (line 233) | function stopJobPolling() { function setGeneratingState (line 241) | function setGeneratingState(active) { function cancelGeneration (line 257) | function cancelGeneration() { function uploadSongs (line 271) | async function uploadSongs() { function generateVideo (line 296) | async function generateVideo() { FILE: tests/conftest.py function session_factory (line 22) | def session_factory(tmp_path: Path): function session (line 43) | def session(session_factory): FILE: tests/test_api_jobs.py function client (line 17) | def client(monkeypatch, session_factory): function test_generate_requires_video_subject (line 22) | def test_generate_requires_video_subject(client): function test_generate_creates_job_and_job_status_is_fetchable (line 31) | def test_generate_creates_job_and_job_status_is_fetchable(client): function test_get_events_respects_after_query_parameter (line 56) | def test_get_events_respects_after_query_parameter(client, session_facto... function test_cancel_job_endpoint_cancels_existing_job (line 74) | def test_cancel_job_endpoint_cancels_existing_job(client, session_factory): function test_cancel_job_endpoint_returns_404_for_unknown_job (line 92) | def test_cancel_job_endpoint_returns_404_for_unknown_job(client): function test_cancel_latest_running_job_returns_404_when_no_active_job (line 101) | def test_cancel_latest_running_job_returns_404_when_no_active_job(client): function test_cancel_latest_running_job_cancels_active_job (line 110) | def test_cancel_latest_running_job_cancels_active_job(client, session_fa... FILE: tests/test_api_misc.py function client (line 16) | def client(): function test_models_endpoint_success_response (line 20) | def test_models_endpoint_success_response(client, monkeypatch): function test_models_endpoint_fallback_on_error (line 35) | def test_models_endpoint_fallback_on_error(client, monkeypatch): function test_upload_songs_requires_files (line 53) | def test_upload_songs_requires_files(client): function test_upload_songs_rejects_non_mp3_files (line 64) | def test_upload_songs_rejects_non_mp3_files(client, monkeypatch, tmp_path): function test_upload_songs_saves_mp3_and_sanitizes_filename (line 87) | def test_upload_songs_saves_mp3_and_sanitizes_filename(client, monkeypat... FILE: tests/test_repository.py function test_create_job_persists_payload_and_queued_event (line 12) | def test_create_job_persists_payload_and_queued_event(session): function test_request_cancel_cancels_queued_job_and_tracks_events (line 27) | def test_request_cancel_cancels_queued_job_and_tracks_events(session): function test_claim_next_queued_job_marks_running_and_skips_cancelled (line 40) | def test_claim_next_queued_job_marks_running_and_skips_cancelled(session): function test_mark_completed_updates_status_and_emits_complete_event (line 53) | def test_mark_completed_updates_status_and_emits_complete_event(session): function test_mark_failed_updates_error_message_and_event (line 66) | def test_mark_failed_updates_error_message_and_event(session): function test_mark_cancelled_sets_status_and_writes_cancelled_event (line 76) | def test_mark_cancelled_sets_status_and_writes_cancelled_event(session): FILE: tests/test_utils.py function test_clean_dir_removes_existing_files_and_directories (line 6) | def test_clean_dir_removes_existing_files_and_directories(tmp_path: Path): function test_choose_random_song_returns_none_if_songs_dir_missing (line 19) | def test_choose_random_song_returns_none_if_songs_dir_missing( function test_choose_random_song_returns_selected_mp3 (line 28) | def test_choose_random_song_returns_selected_mp3(monkeypatch, tmp_path: ... function test_resolve_imagemagick_binary_prefers_configured_existing_path (line 46) | def test_resolve_imagemagick_binary_prefers_configured_existing_path( function test_resolve_imagemagick_binary_falls_back_to_path_lookup (line 58) | def test_resolve_imagemagick_binary_falls_back_to_path_lookup(monkeypatch): FILE: tests/test_worker.py function _disable_cleanup (line 5) | def _disable_cleanup(monkeypatch): function test_process_next_job_returns_false_when_queue_is_empty (line 9) | def test_process_next_job_returns_false_when_queue_is_empty( function test_process_next_job_marks_completed_on_pipeline_success (line 18) | def test_process_next_job_marks_completed_on_pipeline_success( function test_process_next_job_marks_cancelled_on_pipeline_cancelled (line 49) | def test_process_next_job_marks_cancelled_on_pipeline_cancelled( function test_process_next_job_marks_failed_on_pipeline_error (line 75) | def test_process_next_job_marks_failed_on_pipeline_error(monkeypatch, se... function test_job_cancelled_helper_returns_true_for_missing_job (line 100) | def test_job_cancelled_helper_returns_true_for_missing_job( function test_job_cancelled_helper_reflects_cancel_flag (line 108) | def test_job_cancelled_helper_reflects_cancel_flag(monkeypatch, session_... function test_log_event_helper_persists_log_event (line 125) | def test_log_event_helper_persists_log_event(monkeypatch, session_factory):