Skip to main content

Porter Workflow

English | 简体中文

CI PyPI Python 3.11 - 3.13 License: MIT

Porter Workflow: video input, media preparation, subtitle extraction, translation, and subtitled video delivery

Porter Workflow takes a video URL or a local file and produces a localized release: a standardized asset bundle, bilingual and Chinese-only subtitles, and hard-subbed MP4s.

How it works

URL / local file
      │
      ▼
PREPARE     download, standardize, fetch platform subtitles, extract audio
      │
      ▼
TRANSCRIBE  use the platform's subtitle track, or run speech recognition
      │
      ▼
TRANSLATE   produce target-language subtitles (default: zh-Hans)
      │
      ▼
BURN        render bilingual / Chinese-only hard-subbed MP4s

Completed phases are reused on a rerun. --force redoes them, --only-phase stops after one, and --burn skip stops before encoding.

Supported platforms

Platform URL examples Platform subtitle track
YouTube youtube.com, youtu.be Yes
Bilibili bilibili.com, b23.tv, bilibili.tv Yes (CC may require cookies)
TikTok tiktok.com, vm.tiktok.com Yes
X / Twitter x.com, twitter.com No — ASR runs
Instagram instagram.com No — ASR runs
Local file any readable path No — ASR or --subtitle-file

Downloads go through yt-dlp, so other sites it supports may work, but only these platforms have explicit specs. A native track is requested, not guaranteed: rate limiting can make the fetch fail, and the ASR chain then takes over.

Backends by phase

PREPARE

  • URL — yt-dlp download; local file — used in place.
  • FFmpeg normalizes video to H.264/AAC and audio to 16 kHz mono.
  • Deno (or Node ≥ 20) is recommended for YouTube's JS challenges.

TRANSCRIBE

Route Requires Notes
Platform subtitles — Free and exact; preferred when the platform provides them
whisper-local [asr-local] extra Key-free and offline after the model downloads; tried first
whisper-api [llm] extra + API key Any OpenAI-compatible /audio/transcriptions endpoint
videocaptioner External CLI, installed by you GPL-3.0 and python<3.13, so never a declared dependency
--subtitle-file FILE A local SRT Explicit source track; skips platform tracks and ASR

The first available backend wins. --asr-engine NAME moves a named backend to the front but keeps the rest as fallbacks. A Chinese platform track skips the translation phase entirely.

TRANSLATE

Backend Requires Notes
llm [llm] extra + API key Best quality; can also repair transcription errors
bing Nothing Key-free endpoint
google Nothing Key-free endpoint
mymemory Nothing Key-free public API
videocaptioner-llm External CLI GPL-3.0, installed by you
videocaptioner External CLI GPL-3.0, installed by you

The first backend that produces usable text wins. For a Chinese target, a response without CJK characters is rejected and the next backend is tried. --translator NAME promotes a backend to the front, like --asr-engine. --target-lang defaults to zh-Hans.

BURN

Mode Output
dual (default) video_bilingual.mp4 + video_zh.mp4
zh_only video_zh.mp4
bilingual_only video_bilingual.mp4
skip Subtitles only, no video encoding

Burning requires FFmpeg with libass. Fonts, sizes, colors, margins and fades are configurable under the style section.

Install

Requires Python ≥ 3.11.

System dependencies (not Python packages, must be on PATH):

Dependency Needed for Notes
FFmpeg + ffprobe Everything Must be built with libass. Verify: ffmpeg -filters | grep subtitles
Deno (recommended) YouTube downloads yt-dlp ≥ 2025.11.12 needs an external JS runtime; Node ≥ 20 also works
# Recommended: local, key-free, offline transcription
uvx --from "porter-workflow[asr-local]" porter "<URL>"

# Every optional backend, including WebUI support
uvx --from "porter-workflow[all]" porter "<URL>"

# WebUI workbench
uvx --from "porter-workflow[web]" porter-web

# Persistent install
pipx install "porter-workflow[all]"

# Check the environment
porter doctor
Extra Adds Enables
[asr-local] faster-whisper Local Whisper — key-free and offline
[llm] openai, json-repair LLM translation + Whisper API ASR
[images] pillow Cover image handling
[mcp] fastmcp The porter-mcp server
[web] gradio The porter-web workbench
[all] all of the above —

A minimal install without [asr-local] or [llm] can download and translate, but cannot transcribe unless a platform subtitle track exists or the external VideoCaptioner CLI is installed. porter doctor reports the route a job will actually take.

Usage

porter inspect "<URL>"              # Inspect a link without downloading
porter plan "<URL>"                 # Show the exact route and expected failures
porter "<URL>"                      # Full pipeline
porter "<URL>" -o ./porter_output   # Choose the output directory
porter "<URL>" --burn skip          # Subtitles only
porter doctor                       # Diagnose the environment
porter config list                  # Show resolved config (secrets masked)

Output layout

<output_dir>/<video_id>_<safe_title>/
├── raw/
│   ├── video.mp4                 H.264 + AAC + faststart master
│   ├── audio.wav                 16 kHz mono reference track
│   ├── audio_enhanced.wav        denoised track used only for ASR
│   ├── transcript.json/.txt      reconstructed sentence script book
│   ├── subtitle.srt              platform-provided source subtitles, if any
│   ├── cover.jpg
│   └── metadata.json
└── cooked/
    ├── subtitle_bilingual.{srt,ass}
    ├── subtitle_zh.{srt,ass}
    ├── video_bilingual.mp4
    └── video_zh.mp4

Frontends

Frontend Command For
CLI porter Humans and shell scripts
MCP uvx --from "porter-workflow[mcp]" porter-mcp AI agents over stdio JSON-RPC
WebUI uvx --from "porter-workflow[web]" porter-web Humans and agents using the HITL workbench
Agent Skill npx skills add RolinShmily/porter-workflow Agents using the Agent Skills spec

All four call the same engine. MCP setup details are in skills/porter-skill/references/MCP.md; restricted Windows hosts are covered in skills/porter-skill/references/HOSTS.md.

Configuration

Resolved in this order, highest priority first:

  1. --config <path>
  2. $PORTER_CONFIG
  3. Environment variables (they override the selected file)
  4. Nearest project config: porter.json → porter.toml → config.json
  5. User config under platformdirs (only if there is no project config)
  6. Built-in defaults
Section Keys Purpose
top level output_dir, cookies_file, cookies_browser Output location and gated-media access
llm api_key, api_base, model LLM translation, refinement and Whisper API fallback
asr engine, language, audio_denoise, whisper_local_model, whisper_local_device, whisper_local_compute_type, whisper_api_key, whisper_api_base, whisper_model Speech recognition
refine enabled, model LLM transcript cleanup before translation
ffmpeg ffmpeg_path, ffprobe_path, video_codec, preset, crf, pixel_format, audio_codec, audio_bitrate, audio_sample_rate, wav_sample_rate, auto_tune Encoding and hardware tuning
style zh_font, en_font, sizes, colors, outline_*, shadow, margin_*, fade_* ASS subtitle appearance
porter config list                     # Effective values + source, secrets masked
porter config get llm                  # Show one section
porter config set llm.model=deepseek-chat
porter config set llm.api_key=sk-...   # Writes user-level config by default

The complete key table, defaults and examples are in skills/porter-skill/references/CONFIG.md.

Build and develop

Development needs Python 3.11–3.13, uv, FFmpeg + libass, and Deno or Node ≥ 20. The runtime dependencies are yt-dlp[default], requests, pydantic and platformdirs; everything else is an optional extra.

uv sync --extra all --extra dev      # Install exactly what uv.lock pins

ruff check src tests scripts        # Lint; T20 enforces no print() in the engine
mypy src scripts                    # Strict type checking
lint-imports                        # Engine/frontend dependency contracts
pytest -m "not network"             # Offline suite

Repository layout:

src/porter/
├── __init__.py       stable public API (lazy exports), __version__
├── core/             engine — all business logic
├── cli/              CLI frontend
├── mcp/              MCP frontend
└── webui/            Gradio WebUI frontend (HITL workbench)
skills/porter-skill/  Agent Skill assets (SKILL.md, scripts, references)
scripts/              developer / release helper scripts (launcher.py)
docs/                 development, architecture, reference, design, images
tests/{unit,regression,integration}/

License

MIT. See LICENSE. Third-party components and their licences are listed in THIRD_PARTY_NOTICES.md.

Metadata

Release files for porter-workflow 0.3.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for porter-workflow 0.3.2
File Size Uploaded Provenance Actions
porter_workflow-0.3.2.tar.gz 493.4 kB With provenance Details for porter_workflow-0.3.2.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for porter-workflow 0.3.2
File Interpreter ABI Platform Actions
porter_workflow-0.3.2-py3-none-any.whl Python 3 none any Details for porter_workflow-0.3.2-py3-none-any.whl

Total release size: 820.5 kB

Release files / porter_workflow-0.3.2.tar.gz

Download URL porter_workflow-0.3.2.tar.gz
Size 493.4 kB
Tags Source
SHA-256 checksum
How to use checksums
f53d28337796a1f5ae6d6d8c0b35315e7ef7781e807d7f8f380a2f8c6e84a19b
BLAKE2b-256 checksum
How to use checksums
03bda935b306f4e803bce0b22d9fa4deb5bb38728a7c0f077bccb4b4e927b9e2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 11, 2026.

Transparency log

Release files / porter_workflow-0.3.2-py3-none-any.whl

Download URL porter_workflow-0.3.2-py3-none-any.whl
Size 327.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
fbaa2f6e8af420947f01dc71af58ae8a0d4fd7679696c32a8f7f299d2e215f9f
BLAKE2b-256 checksum
How to use checksums
7c3ac64e3cf6262ff4f721ccd6b7181d9ee5444f0b98e7ae847a653a205fb027
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 11, 2026.

Transparency log

Security for porter-workflow 0.3.2

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

Both files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for porter_workflow-0.3.2.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 11, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page