Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,27 @@ MEDIA_URL_TTL_SECONDS=3600
JOB_HEARTBEAT_SECONDS=30
JOB_STALE_MINUTES=40

# ─── Import from URL ─────────────────────────────────────────────────────────
#
# Pasting a YouTube (or Rumble, Odysee, Vimeo, …) link downloads it with yt-dlp. See
# docs/url-import.md, including what to do when imports start failing — YouTube
# changes under yt-dlp every few weeks, and the fix is to bump its pin and rebuild.

# Tallest video to fetch. 1080p is the highest YouTube offers as H.264, which plays in
# every browser; above it you get VP9/AV1, which Safari may refuse.
URL_IMPORT_MAX_HEIGHT=1080

# Most videos one playlist or channel link may queue.
URL_IMPORT_MAX_PLAYLIST_ITEMS=200

# Optional. A Netscape cookies.txt *inside the container*, for YouTube's "confirm you're
# not a bot" wall (common on VPS/datacenter IPs) and age-restricted videos. Mount it
# read-only, e.g. in docker-compose.override.yml:
# services: { backend: { volumes: ["./secrets/cookies.txt:/app/secrets/cookies.txt:ro"] } }
# and set: URL_IMPORT_COOKIES_FILE=/app/secrets/cookies.txt
# Treat that file like a password — it is a signed-in session for the account it came from.
URL_IMPORT_COOKIES_FILE=

# ─── Development only ────────────────────────────────────────────────────────

# "development" enables DEV_AUTH_USER below. Anything else, and it is ignored.
Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ user row. The changes that makes possible are specified in

- **Ingest with no friction** — drop files in with a name and nothing else. Everything
beyond that is optional and can be filled in later, by hand or by AI.
- **Import from a link** — paste a YouTube (or Rumble, Odysee, Vimeo…) URL and it arrives
titled, attributed, tagged and split into its chapters, with the site's captions as a
transcript when there is no Deepgram key. Playlists too. See
[`docs/url-import.md`](docs/url-import.md).
- **Find the moment** — full-text search over names, descriptions, summaries, tags and
transcripts, fused with semantic search so half-remembered wording still lands. Hits
in audio and video come back with a timestamp you can jump straight to.
Expand Down
13 changes: 13 additions & 0 deletions backend/app/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,19 @@ class Settings(BaseSettings):
# long upload, both of which contend with serving the API from the same container.
enrichment_concurrency: int = 1

# ─── import from URL ─────────────────────────────────────────────────────
# The tallest video an import will fetch. 1080p is where YouTube stops offering
# H.264, which is the codec every browser (Safari included) plays without a
# re-encode — and a ninety-minute interview is ~1-2 GB here against 4-8 GB at 4K.
url_import_max_height: int = 1080
# A channel's "videos" tab is a playlist too, and can hold thousands. One paste
# should not be able to queue a week of downloads.
url_import_max_playlist_items: int = 200
# A Netscape-format cookies.txt, as a path inside the container. Empty by default.
# For YouTube's "confirm you're not a bot" wall on datacenter IPs, and for
# age-restricted or members-only videos; mount the file read-only and point here.
url_import_cookies_file: str = ""

# ─── development ─────────────────────────────────────────────────────────
# Bypasses token verification and acts as this user id. Refused unless
# `environment` is "development", so it cannot be switched on in production by
Expand Down
Loading
Loading