Add cookie file upload

This commit is contained in:
2026-05-22 20:47:21 +01:00
parent a25a60f217
commit 75522ede50
3 changed files with 67 additions and 8 deletions

View File

@@ -78,7 +78,7 @@ Open `http://127.0.0.1:7860` and submit a YouTube URL. Jobs run through the same
The OpenAI-compatible translation endpoint, API key, and model can be changed in the UI under **OpenAI-Compatible Settings**. Click **Save Settings** to persist them to `.cache/web_settings.json` for future web jobs. Unsaved values in the fields are still used for the next job you start.
You can also upload a local `.mp4` instead of entering a YouTube URL. Uploaded videos are staged under `.cache/uploads` and processed with the same transcription, translation, dubbing, and render pipeline.
You can also upload a local `.mp4` instead of entering a YouTube URL. Uploaded videos are staged under `.cache/uploads` and processed with the same transcription, translation, dubbing, and render pipeline. Restricted YouTube videos can use the **Upload Cookies File** control instead of typing a local cookies path.
### Docker

View File

@@ -5,7 +5,13 @@ from __future__ import annotations
import sys
import web_app
from web_app import build_pipeline_command, create_app, load_translation_settings, save_translation_settings
from web_app import (
_stage_uploaded_cookies,
build_pipeline_command,
create_app,
load_translation_settings,
save_translation_settings,
)
def test_build_pipeline_command_uses_cli_parser_defaults():
@@ -91,3 +97,29 @@ def test_load_translation_settings_uses_env_defaults(tmp_path, monkeypatch):
"api_key": "env-key",
"model": "env-model",
}
def test_stage_uploaded_cookies_copies_to_upload_dir(tmp_path, monkeypatch):
upload_dir = tmp_path / "uploads"
source_file = tmp_path / "cookies.txt"
source_file.write_text("# Netscape HTTP Cookie File\n", encoding="utf-8")
monkeypatch.setattr(web_app, "UPLOAD_DIR", upload_dir)
staged_path = _stage_uploaded_cookies(str(source_file))
assert staged_path.endswith(".txt")
assert staged_path != str(source_file)
assert upload_dir in web_app.Path(staged_path).parents
assert web_app.Path(staged_path).read_text(encoding="utf-8") == "# Netscape HTTP Cookie File\n"
def test_stage_uploaded_cookies_rejects_unsupported_extension(tmp_path):
source_file = tmp_path / "cookies.json"
source_file.write_text("{}", encoding="utf-8")
try:
_stage_uploaded_cookies(str(source_file))
except ValueError as exc:
assert "Expected one of" in str(exc)
else:
raise AssertionError("Expected ValueError for unsupported cookie upload")

View File

@@ -179,17 +179,35 @@ def _form_to_cli_args(form: dict[str, str | bool]) -> list[str]:
def _stage_uploaded_mp4(uploaded_file: str | None) -> str:
return _stage_uploaded_file(uploaded_file, allowed_suffixes={".mp4"}, fallback_name="upload")
def _stage_uploaded_cookies(uploaded_file: str | None) -> str:
return _stage_uploaded_file(
uploaded_file,
allowed_suffixes={".txt", ".cookies", ".cookie"},
fallback_name="cookies",
)
def _stage_uploaded_file(
uploaded_file: str | None,
allowed_suffixes: set[str],
fallback_name: str,
) -> str:
if not uploaded_file:
return ""
source_path = Path(uploaded_file)
if source_path.suffix.lower() != ".mp4":
raise ValueError("Only MP4 uploads are supported.")
suffix = source_path.suffix.lower()
if suffix not in allowed_suffixes:
expected = ", ".join(sorted(allowed_suffixes))
raise ValueError(f"Unsupported upload type. Expected one of: {expected}.")
if not source_path.exists():
raise FileNotFoundError(f"Uploaded file not found: {source_path}")
safe_stem = "".join(char if char.isalnum() or char in {"-", "_"} else "_" for char in source_path.stem)
staged_name = f"{uuid.uuid4().hex[:12]}_{safe_stem or 'upload'}.mp4"
staged_name = f"{uuid.uuid4().hex[:12]}_{safe_stem or fallback_name}{suffix}"
UPLOAD_DIR.mkdir(parents=True, exist_ok=True)
staged_path = UPLOAD_DIR / staged_name
shutil.copy2(source_path, staged_path)
@@ -267,7 +285,7 @@ def _start_job(
whisper_model: str,
mix_mode: str,
browser: str,
cookies: str,
cookies_upload: str | None,
lmstudio_base_url: str,
lmstudio_api_key: str,
lmstudio_model: str,
@@ -282,6 +300,11 @@ def _start_job(
except (OSError, ValueError) as exc:
message = str(exc) or "Invalid uploaded MP4."
return "", message, message, gr.update(choices=_output_choices())
try:
cookies = _stage_uploaded_cookies(cookies_upload)
except (OSError, ValueError) as exc:
message = str(exc) or "Invalid uploaded cookies file."
return "", message, message, gr.update(choices=_output_choices())
form = {
"url": url,
@@ -382,7 +405,11 @@ def create_app() -> gr.Blocks:
choices=["", "chrome", "edge", "firefox", "brave"],
value="",
)
cookies = gr.Textbox(label="Cookies File", placeholder=r"C:\path\to\cookies.txt")
cookies_upload = gr.File(
label="Upload Cookies File",
file_types=[".txt", ".cookies", ".cookie"],
type="filepath",
)
with gr.Accordion("OpenAI-Compatible Settings", open=False):
lmstudio_base_url = gr.Textbox(
@@ -432,7 +459,7 @@ def create_app() -> gr.Blocks:
whisper_model,
mix_mode,
browser,
cookies,
cookies_upload,
lmstudio_base_url,
lmstudio_api_key,
lmstudio_model,