Skip to content
knowledgefxgPublic

About

Turn a YouTube video or a local file into a subtitled video on your own computer, and keep the Chinese and English subtitles, transcripts, and vocabulary so you can study with the picture.

Resources

Stars

44 stars

Watchers

0 watching

Forks

Repository files navigation

Transyt

中文

Turn a YouTube video or a local file into a subtitled video on your own computer, and keep the Chinese and English subtitles, transcripts, and vocabulary so you can study with the picture.

Transcription runs locally with Whisper. The audio is not sent anywhere else. Translation uses the API you configure. Jobs, videos, and API keys stay under data/ by default, or under TRANSYT_DATA_ROOT when set (for example /data in Docker). Those paths are listed in .gitignore.

What it does

  • Download a YouTube video, or upload a local file (mp4, mov, mkv, webm, m4v, up to 2GB)
  • Extract the audio, transcribe it with word-level timestamps, then split it on sentences and pauses
  • Translate the source into Chinese. Subtitles can be Chinese only, English only, or bilingual
  • For bilingual subtitles, put Chinese or English on top. Each language stays on its own line, with its own size and color
  • Burn the subtitles into the picture, or produce a transcript only
  • Study beside the video: read subtitles, extract vocabulary, and save sentences and words
  • Organize projects in folders and search old videos by title

Only one job runs at a time. Later submissions wait in a queue. If the dev server or the production process restarts, a running job is interrupted. Once transcription has written cues.json, you can continue with translation and burning.

Install these yourself

The 一键安装 button on the page does not install any of the following. Get them ready before you clone the project:

You need Why
Node.js 18.18 or newer For npm install and npm run dev
Python 3.9 or newer python3 or python on PATH. 3.11 or 3.12 is recommended. The button only uses it to create a project virtual environment. It does not install Python for you
The Windows VC++ runtime Without it, faster-whisper may install and then fail to load. Install the Microsoft Visual C++ 2015–2022 Redistributable (x64)
ffmpeg on Linux, or on Windows that is not 64-bit Those systems have no ready download. Install a full ffmpeg build that includes libass

On Windows, install Python from python.org and tick Add python.exe to PATH. Do not copy node_modules from a Mac to Windows. Run npm install again in the project directory on the other system.

Download and start

git clone https://github.com/knowledgefxg/Transyt.git
cd Transyt
npm install
npm run dev

You can also download the ZIP from the GitHub repository, unzip it, and run the last two commands in that folder. The repository does not include node_modules, videos, or API keys.

Open http://localhost:3000.

For production:

npm run build
npm start

Docker

The image is Debian-based (node:20-bookworm-slim) with ffmpeg, python3, and python3-venv. At build time it also creates /opt/transyt-venv and installs faster-whisper and yt-dlp there. The app picks that up via TRANSYT_BUNDLED_VENV (set in the Dockerfile and docker-compose.yml), so you normally do not need one-click install for Whisper or yt-dlp inside Docker.

MLX does not run inside a Linux container; transcription uses faster-whisper only.

Prerequisites

  • Docker Desktop (Mac / Windows) or Docker Engine with the Compose plugin (Linux).
  • Clone the repo and cd to the project root (where docker-compose.yml lives).

How to start

Detached (recommended) — keeps running after you close the terminal:

cd /path/to/Transyt
docker compose up --build -d
# or: npm run docker:up

Foreground — logs stream in the terminal; Ctrl+C stops the container:

docker compose up --build

On slow or blocked networks, stack the China mirror overlay:

docker compose -f docker-compose.yml -f docker-compose.cn.yml up --build -d
# or: npm run docker:up:cn

The first run builds the image and may take several minutes. Then open http://localhost:3000.

Logs

docker compose logs -f transyt

Stop and exit

Goal Command
Stop containers, keep data docker compose stop
Remove containers, keep volumes (jobs and settings survive the next up) docker compose down
Remove containers and named volumes (wipes /data in the stack — use with care) docker compose down -v
Start again without rebuilding docker compose up -d

down does not remove images; use docker image rm or docker builder prune if you need to reclaim disk.

Port

By default host 3000 maps to container port 3000. If it is taken, change ports in docker-compose.yml (e.g. "8080:3000") and open http://localhost:8080.


Compose mounts a named volume at /data. To use a host folder instead:

# docker-compose.yml — replace the volumes block with:
    volumes:
      - ./docker-data:/data

Environment:

Variable Meaning
TRANSYT_DATA_ROOT Where jobs, settings, optional user venv, models, and any extra binaries live. Default in the image is /data.
TRANSYT_BUNDLED_VENV Path to the pre-built venv with Whisper and yt-dlp. Default is /opt/transyt-venv.

You still need to save your translation API in the app (or it will not translate). The first precise model download is large and goes under <data>/models; keep the volume on a disk with enough space.

GPU note: the default setup does not pass NVIDIA devices into the container. Transcription uses CPU unless you extend the image and compose file yourself.

Build fails: cannot reach Debian or Docker Hub

Typical log lines:

  • Unable to connect to deb.debian.org with an IP like 198.18.0.59: that range is often used by VPN/proxy fake-ip DNS. The container cannot actually reach the real mirror. Turn off fake-ip for Docker builds, or point Docker’s DNS to something stable (e.g. 8.8.8.8 in Docker Desktop → Settings → Docker Engine → dns), or use a mirror (below).
  • failed to resolve source metadata for docker.io/library/node / timeout to registry-1.docker.io: your machine cannot pull the base image. Configure a working HTTP/HTTPS proxy in Docker Desktop, or use a registry mirror (common on networks in mainland China).

Optional China-friendly build (switch Debian + pip + npm registries during docker build only):

docker compose -f docker-compose.yml -f docker-compose.cn.yml up --build -d
# or: npm run docker:up:cn

Or pass build args manually, for example:

docker build -t transyt \
  --build-arg APT_MIRROR=http://mirrors.aliyun.com/debian \
  --build-arg APT_SECURITY_MIRROR=http://mirrors.aliyun.com/debian-security \
  --build-arg PIP_INDEX_URL=https://pypi.tuna.tsinghua.edu.cn/simple \
  --build-arg NPM_REGISTRY=https://registry.npmmirror.com \
  .

You still need to be able to docker pull node:20-bookworm-slim once; if that fails, fix Docker Hub access first (VPN, proxy, or mirror).

One-click install

After you open the app, the home page lists anything else that is missing. Click 一键安装. It installs only what is missing under TRANSYT_DATA_ROOT (default ./data on the host, /data in Docker), and leaves the system Python alone.

The home page banner lists missing tools, with a one-click install button on the right

Path What it installs
data/venv faster-whisper and yt-dlp. On Apple silicon it also tries mlx-whisper, then keeps using faster-whisper if that fails
data/bin ffmpeg and ffprobe with libass, on Mac and 64-bit Windows

Python packages go into a project virtual environment, so Homebrew’s PEP 668 error does not apply. Already-installed tools are left as they are. The app uses a project-local copy when it exists, otherwise the command on PATH.

Command Use
ffmpeg, ffprobe Extract audio and burn subtitles. ffmpeg must include libass
yt-dlp Download YouTube videos
python3 or python Create the project environment and run transcription

The log under that banner shows what is being installed. If it fails, the page keeps the error and a retry button. Typical causes are a missing or too-old Python, no network to the package index, a full disk, or a missing VC++ runtime on Windows.

The first transcription also downloads a Whisper model (about 1.5GB for the precise model) into <data root>/models. That happens when a job runs, not when you click the install button.

You can still install the same tools yourself. See Install by hand at the end.

Translation API

Translation API, at the top right, stores one configuration shared by subtitle translation and vocabulary extraction. It is written to data/settings.json. The app is not tied to one provider. Any service with an OpenAI-compatible Chat Completions API works, including official APIs, gateways, and a local compatible server.

Translation API: base URL, model name, API key, and download proxy

Requests are POST with an Authorization: Bearer <key> header and a body that includes model, temperature: 0.2, and messages. Subtitle translation asks the model to return JSON, one item per source line. Vocabulary extraction uses the same settings to pick words, phrases, collocations, idioms, slang, and usage from the source.

The four fields

Field How to fill it
Base URL The API root from the provider’s docs, usually ending in /v1, such as https://api.openai.com/v1. The app appends /chat/completions. If the docs already give a full .../chat/completions URL, paste that as-is and it will not be appended twice
Model The model ID available at that URL, such as gpt-4o-mini, deepseek-chat, or qwen-plus. Do not put the API key here
API key The key issued by the provider. After a key is saved, leaving this box empty and saving again keeps the old key. The page never shows the key back. If an sk- key is entered in the model field by mistake, saving moves it into the key field. When the base URL contains DeepSeek, the model becomes deepseek-chat; otherwise it becomes gpt-4o-mini
Download proxy Used only for YouTube downloads. Leave it empty if you do not need one. Translation requests do not use this proxy. A typical value is http://127.0.0.1:7890

The base URL, model, and key have to succeed together as one chat request. When you change providers, change all three. Changing only the model and keeping the old URL often returns 404 or “model not found”.

If you start a job before a key is saved, the transcript is kept. After you add a key, translation and burning can continue. Vocabulary extraction in study mode uses this same configuration.

The rows below are common examples, not a support list. Follow the docs for the service you use:

Service Base URL Example model
OpenAI https://api.openai.com/v1 gpt-4o-mini
DeepSeek https://api.deepseek.com/v1 deepseek-chat
Qwen (compatible mode) https://dashscope.aliyuncs.com/compatible-mode/v1 qwen-plus
Local server or gateway The root URL from its docs A model ID that service lists

Interface

The home page puts the job form on the left and the current job, downloads, and recent list on the right. Clicking TRANSYT at the top left returns home and clears the form for this run. The saved translation API and key stay in place.

Home: processing options on the left, the finished video, downloads, and recent jobs on the right

The recent list shows 8 jobs per page. Page controls appear only after the ninth job.

Subtitle style

Option What gets burned Size and color
Chinese only Chinese only Chinese size and color
English only The English source only English size and color
Bilingual One line of each Both pairs, and a choice of which language is on top

Defaults are Chinese at size 20 in white, and English at size 16 in pale yellow. Sizes run from 12 to 64. These choices are stored locally and kept for the next visit.

Study mode

After a job with video finishes, you can enter study mode. The picture stays on the left. Subtitles, vocabulary, and saved items stay on the right.

Study mode: video on the left, vocabulary extracted by level on the right

  • Subtitles. Click a line to jump to that time. The star saves the sentence.
  • Vocabulary. Choose a CEFR range from A1 to C2, and the kinds you want: words, phrases, collocations, idioms, slang, and usage. Then extract. Each item includes a short Chinese gloss and IPA. If nothing in the source reaches the chosen range, the list stays empty instead of filling in easier items. Click a word to jump to its time, use the speaker for a system voice, and click the source sentence to translate it into Chinese.
  • Saved. Sentences and words saved from this video.

Pronunciation uses the browser’s system voices. The word is not uploaded. Local voices on a Mac work offline.

Saved items in project management collect sentences and words from every video. Opening one jumps into study mode for that video.

Projects

  • Projects. Filter by folder and search by title. Search applies together with the current folder.
  • Folders. Create and delete folders. Deleting a folder sends its projects back to uncategorized.
  • Opening a project returns to the home page. Deleting a project also deletes its downloaded video and subtitles. If the same YouTube video was processed more than once, those runs are removed together.

What one job does

  1. Download or import. YouTube videos are downloaded with yt-dlp. Local files are stored as they are. If a proxy is needed, the download uses the proxy set under Translation API.
  2. Extract audio. ffmpeg pulls the audio track for transcription.
  3. Transcribe. Local Whisper produces a timestamped transcript. The precise model is about 1.5GB on first download. The fast model is smaller. Source language can be auto-detect, English, Japanese, Korean, French, Spanish, German, or Chinese.
  4. Translate. For a non-Chinese video, each subtitle line is translated into Chinese, 12 lines per request, with up to 3 requests in flight. A detected Chinese source skips translation and uses the original text as Chinese. If you chose English-only subtitles but the source is Chinese, there is no English to burn, so the job falls back to Chinese only.
  5. Burn. With “burn into the video” and a picture track, ffmpeg with libass burns the subtitles in. “Transcript only”, or a file with no picture, skips this step.
  6. Transcript. Writes a Chinese Markdown transcript. When the source is not Chinese, it also keeps a source transcript.

Chinese lines drop trailing punctuation and stay on one line. Bilingual cues place one language above the other and share the same timestamps.

Output

Each job is stored in data/jobs/<id>/. The id is 16 hexadecimal characters. Common files:

File Contents
video.mp4 The downloaded or imported source video
burned.mp4 The video with subtitles burned in
zh.srt Chinese subtitles
en.srt English subtitles, written when the source is not Chinese, with the same timestamps as the Chinese file
subs.ass The subtitle file actually used for burning
source.srt The transcript with its original timestamps
transcript-zh.md Chinese transcript
transcript-src.md Source transcript, written when the source is not Chinese
lexicon.json Vocabulary extracted by level. Created when you extract it in study mode
cues.json Segments and timestamps. With this file, the job can resume at translation
job.json Status, options, and stages for this job

The finished video, subtitles, and transcripts can be downloaded from the home page and from project management.

Pause, failure, and resume

You can pause while a job is running. Pausing stops the current download, transcription, or burn. On Windows this uses taskkill.

If translation fails partway, or a restart interrupts the job after transcription has finished, the page offers to continue translation and burning. Lines that are already translated are kept. Missing lines are requested again.

A job that is still running cannot be deleted. Wait until it finishes or pause it first.

Install by hand if you prefer

If you are not using the page button, install one transcription library. MLX is used when it is already installed:

System Library Precise model Fast model
Apple silicon Mac mlx-whisper mlx-community/whisper-large-v3-turbo mlx-community/whisper-medium-mlx
Windows, and other machines without MLX faster-whisper large-v3-turbo medium

The two model downloads are not interchangeable. Switching machines or engines downloads the model again.

Mac:

brew install ffmpeg yt-dlp
pip3 install mlx-whisper

Windows, with the tools on PATH:

pip install faster-whisper yt-dlp

Development

FileNotFoundError: ... 'ffmpeg' during transcription

MLX invokes ffmpeg through PATH when reading audio. Older versions used the full data/bin/ffmpeg path for audio extraction but did not add that directory to Python's PATH, so tool checks and extraction could succeed while transcription failed.

Update the project and restart the server. The project now adds data/bin to child processes' PATH. If ffmpeg has not been installed, use the one-click installer first. On older versions, Mac users can also run brew install ffmpeg, check that ffmpeg -version works in the terminal used to start the server, then restart and submit the job again. This error means the ffmpeg executable was not found; it does not by itself indicate a Python 3.13 compatibility problem.

Check subtitle segmentation:

npm run test:segment

About

Turn a YouTube video or a local file into a subtitled video on your own computer, and keep the Chinese and English subtitles, transcripts, and vocabulary so you can study with the picture.

Resources

Stars

44 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages