Porter Skill(스트리밍 미디어 운반공)
비디오 링크를 중국어 하드 자막이 포함된 완성본으로 만듭니다. 네 단계를 순서대로 실행합니다: 획득 → 전사 → 번역 → 인코딩, 각 단계의 결과물을 디스크에 기록하므로 중간에 실패해도 완료된 부분이 손실되지 않습니다.
⚠️ 사전 조건: 전사를 위한 키 필요
이 부분을 먼저 확인해야 합니다. 그렇지 않으면 작업이 전사 단계에서 실패합니다.
| 기능 | 키 필요 여부 |
|---|---|
| 다운로드, 번역, 인코딩 | 필요 없음 |
| 음성 전사(ASR) | OPENAI_API_KEY (또는 WHISPER_API_KEY) 필요, 또는 VideoCaptioner CLI 설치 필요 |
| 플랫폼 기본 자막 트랙 (YouTube / Bilibili 등) | 필요 없음 – 기본 트랙이 있으면 ASR을 실행하지 않음 |
v0.1에서 주장한 "순수 Python, 키 제로 폐쇄 루프"는 더 이상 유효하지 않습니다: 모든 키 없는 음성 인식 엔드포인트가 중단되었습니다 (2026-09-22 기준; 또는 [asr-local] extra를 사용하여 키 없는 로컬 인식 가능). 키가 없고 비디오에 플랫폼 자막 트랙도 없는 경우 작업은 transcribe 단계에서 every speech-to-text backend failed 오류로 종료됩니다.
따라서: 먼저 plan을 실행하세요. 이 명령은 이 비디오가 플랫폼 자막 트랙을 사용할지 ASR을 사용할지, 그리고 가능한지 여부를 직접 알려줍니다.
호출 진입점
CLI 진입점은 uvx를 통해 실행됩니다. Windows PowerShell은 기본 .ps1을 사용하고, Git Bash / WSL을 가정하지 마세요:
| 스크립트 | 용도 |
|---|---|
scripts/porter.sh | Bash 메인 진입점, porter CLI로 전달. |
scripts/porter.ps1 | Windows PowerShell 메인 진입점, inspect / plan / run / jobs 등의 하위 명령을 지원합니다. |
scripts/inspect.sh | Bash 사전 검사, porter.sh inspect와 동일. |
scripts/bootstrap.sh | 리포지토리 체크아웃에서 .venv를 생성하는 대체 진입점; 스킬과 함께 Python 소스 코드를 설치하지 않습니다. |
# 사전 검사
<SKILL_DIR>/scripts/inspect.sh "https://youtu.be/dQw4w9WgXcQ"
# 계획
<SKILL_DIR>/scripts/porter.sh plan "https://youtu.be/dQw4w9WgXcQ"
# 실행
<SKILL_DIR>/scripts/porter.sh run "https://youtu.be/dQw4w9WgXcQ" -o ./porter_output
Windows PowerShell에서는 & '<SKILL_DIR>\scripts\porter.ps1' inspect '<URL>' --json을 사용하며, plan / run / jobs도 동일한 진입점을 호출합니다. inspect.sh와 아래의 nohup, grep 명령은 Bash 예시이므로 PowerShell에 그대로 붙여넣을 수 없습니다.
uvx를 처음 실행하면 네트워크를 통해 종속성을 확인합니다. 기본적으로 porter-workflow[llm]만 설치됩니다 (기본 패키지에는 yt-dlp가 포함됨). 로컬 ASR이 필요한 경우 사용자 동의 하에 PORTER_SKILL_SPEC=porter-workflow[llm,asr-local]을 설정합니다. 오프라인 설치 시 리포지토리 체크아웃에서 로컬 종속성을 준비하고, 스킬 디렉토리에 소스 코드가 포함되어 있다고 가정하지 마십시오.
작업 영역만 쓸 수 있는 호스트에서는 먼저 허용된 절대 디렉토리를 확인하고, PORTER_SKILL_STATE_DIR을 그 디렉토리의 .state로 설정한 다음, porter.sh --host-check 또는 porter.ps1 --host-check를 실행합니다. 그러면 uv, yt-dlp 및 작업 레지스트리 캐시가 해당 디렉토리로 리디렉션됩니다 (호스트에서 설정된 캐시 경로를 덮어씀). 출력 -o도 허용된 디렉토리에 있어야 합니다. 설정되지 않은 경우 호스트 기본 경로가 유지됩니다. 명령, 제한 사항 및 Windows 예제는 references/HOSTS.md를 참조하십시오.
워크플로우 폐쇄 루프
순서대로 실행합니다. 각 단계는 다음 단계보다 비용이 적게 들며, 오랜 시간이 걸리는 계산을 시작하기 전에 잘못된 입력을 거부하는 것을 목표로 합니다.
1. 사전 검사 – inspect
<SKILL_DIR>/scripts/inspect.sh "<URL>" --json
플랫폼, 제목, 길이, 해상도, 화면비, 자막 트랙 유무를 반환합니다. 미디어를 다운로드하기 전에 완료되며, 몇 초가 걸립니다.
해석: is_valid가 "링크 사용 가능"을 의미하며, ok는 "호출 성공"만 의미합니다. 링크가 유효하지 않으면 is_valid=false이며, 이 경우 재시도하지 마십시오 – 끊어진 링크를 다시 시도하는 것은 의미가 없습니다.
종료 코드 1은 링크를 사용할 수 없음을 나타냅니다.
2. 계획 – plan
<SKILL_DIR>/scripts/porter.sh plan "<URL>" --json
이 단계가 가장 시간을 절약해 줍니다. "이 비디오가 어떻게 처리되고, 가능한지"를 알려줍니다:
subtitles.route:platform(플랫폼 기본 자막 트랙 사용) 또는asr(음성 인식 실행)translation.needed: 이미 중국어 트랙이 있는 경우false이며, 번역 단계를 건너뛸 수 있습니다.feasible/blocking_issues:false이면 중단하고 작업을 시작하지 마십시오.notes: 필독. 가장 중요한 두 가지:- 플랫폼 자막 트랙은 "요청되었으나 보장되지 않음" – 가져오기가 실패할 수 있음 (플랫폼 속도 제한, HTTP 429) 및 음성 인식으로 대체됨
- 사용 가능한 인식 백엔드가 모두 테스트되지 않은 리버스 엔지니어링 엔드포인트인 경우 note에 명시됨
종료 코드 1은 불가능함을 나타냅니다.
3. 사용자 확인
하나의 작업은 수백 MB를 다운로드하고 몇 분 동안 실행될 수 있습니다. plan의 결론을 사용자에게 보고하고 실행 전에 동의를 받으십시오 (어떤 트랙을 사용할지, 어떤 단계를 실행할지, 인코딩할지 여부). feasible=false인 경우 차단 문제를 보고하고 작업을 시작하지 마십시오.
4. 실행 – run
<SKILL_DIR>/scripts/porter.sh run "<URL>" -o ./porter_output
긴 비디오의 경우 포그라운드에서 호출하여 완료될 때까지 기다리지 마십시오. 백그라운드에서 시작한 다음 작업 레지스트리를 폴링하십시오:
nohup <SKILL_DIR>/scripts/porter.sh run "<URL>" -o ./porter_output > run.log 2>&1 &
# 폴링 (작업 기록은 공유 레지스트리 파일에 기록되며, 프로세스 간에 표시됨)
<SKILL_DIR>/scripts/porter.sh jobs list
<SKILL_DIR>/scripts/porter.sh jobs status <job_id>
PowerShell의 경우 호스트에서 제공하는 백그라운드 작업 도구를 사용하여 & '<SKILL_DIR>\scripts\porter.ps1' run ...을 비동기적으로 시작하고, 동일한 PORTER_SKILL_STATE_DIR을 사용하여 jobs status를 계속 폴링하십시오. 오래 걸리는 명령의 진행 상황을 끝날 때까지 모아서 출력하는 데 Out-String을 사용하지 마십시오.
하지 마십시오 – "도구 시간 제한을 1200초로 설정"하여 긴 작업을 억지로 처리하는 것 (v0.1의 방식). 그렇게 하면 비디오가 더 길어질 때 여전히 실패하고, 실패 시 진행 상황을 전혀 얻을 수 없습니다. 작업 레지스트리는 이를 위해 설계되었습니다.
5. 품질 검사 (필수)
종료 코드만 보고 완료되었다고 판단하지 마십시오. 최소한 다음을 확인하십시오:
# 1. 중국어 자막이 실제로 존재하고 CJK 문자를 포함하는지 확인 ("번역되지 않은 가짜 자막" 방지)
grep -qP '[\x{4e00}-\x{9fff}]' ./porter_output/<task>/cooked/subtitle_zh.srt \
&& echo "OK: 중국어 포함" || echo "FAIL: 중국어 없음"
# 2. 완성본이 디코딩 가능하고 moov atom이 손상되지 않았는지 확인 (게시 중단 파일 방지)
ffprobe -v error -show_entries format=duration -of csv=p=0 ./porter_output/<task>/cooked/video_zh.mp4
완성본 크기가 비정상적으로 작으면 일반적으로 인코딩 실패를 의미하며, 비디오가 짧은 것을 의미하지는 않습니다.
6. 오류 발생 시
<SKILL_DIR>/scripts/porter.sh doctor # 이 머신에서 작업 가능 여부 확인: ffmpeg/libass, JS 런타임, 글꼴, 인코더
<SKILL_DIR>/scripts/porter.sh config list # 구문 분석된 구성 (키는 마스킹됨)
일반적인 매개변수
# 자막만, 인코딩하지 않음
run "<URL>" --burn skip
# 중국어 완성본만 (이중 언어 생성하지 않음)
run "<URL>" --burn zh_only
# 출력 디렉토리 / 대상 언어 지정
run "<URL>" -o /path/to/out --target-lang zh-Hans
# 특정 백엔드를 우선적으로 사용 (나머지는 여전히 대체 백엔드로 사용, "해당 백엔드만 사용"이 아님)
run "<URL>" --translator google
run "<URL>" --asr-engine whisper-api
# 이 작업에 다른 LLM 모델 사용 (구성 변경 없음)
run "<URL>" --llm-model deepseek-reasoner
# 기존 소스 자막이 있는 경우: 직접 사용, 인식 실행하지 않음 (.srt / .vtt)
run "<URL>" --subtitle-file ./my_subtitles.srt
# 로그인이 필요한 비디오
run "<URL>" --cookies-from-browser chrome
run "<URL>" --cookies ./cookies.txt
# 재실행 (캐시된 단계 결과 무시)
run "<URL>" --force
# 스크립트에서 사용하기 위한 JSON 출력
run "<URL>" --json
--only-phase의 의미는 "이 단계까지" 이며, "이 단계만 실행"이 아닙니다 – 각 단계는 이전 단계의 출력을 필요로 하므로 이전 단계도 계속 실행됩니다.
결과물 구조
<task_dir>/
├── raw/ # 마스터 및 중간 결과물
│ ├── video.mp4 # 표준화된 마스터 (무손실 스트림 복사, 재인코딩 없음)
│ ├── audio.wav # 기준 오디오 트랙
│ ├── audio_enhanced.wav # ASR 전용 강화 오디오 트랙 (노이즈 감소 + 음성 이퀄라이제이션), 완성본에서는 사용되지 않음
│ ├── subtitle.srt # 소스 언어 자막 (플랫폼 트랙 또는 ASR 결과)
│ ├── transcript.json/.txt # 구조화된 대본
│ ├── cover.jpg
│ └── metadata.json
└── cooked/ # 완성본
├── subtitle.srt / .ass # 이중 언어
├── subtitle_zh.srt / .ass # 중국어 전용
├── video_bilingual.mp4 # 이중 언어 하드 자막 완성본
└── video_zh.mp4 # 중국어 전용 하드 자막 완성본
완성본의 오디오는 직접 복사 (-c:a copy)되어 원본 마스터에서 가져오며, 강화 오디오 트랙은 인식 전용으로 사용됩니다 – 인식 정확도와 완성본 음질을 모두 얻습니다.
구성
구성 검색 순서 (나중에 오는 것이 이전 것을 덮어씀):
- 내장 기본값
- 환경 변수:
OPENAI_API_KEY,OPENAI_BASE_URL,OPENAI_MODEL,WHISPER_API_KEY,PORTER_ASR_ENGINE - 사용자 구성 (
porter config list는 실제 경로를 출력함) - 프로젝트 구성: 현재 디렉토리의
porter.json/porter.toml/config.json --config <path>
전체 키 목록은 references/CONFIG.md를, 템플릿은 assets/config.example.json를 참조하십시오.
MCP를 통한 사용 (선택 사항이지만 더 나은 방법)
호스트가 porter MCP 서버를 이미 구성한 경우 셸 대신 이를 우선적으로 사용하십시오:
- 구조화된 결과 제공, stdout 구문 분석 불필요 (셸 이스케이프 및 인코딩 문제 회피)
porter_job_start가 즉시 반환되고porter_job_status로 폴링하여 긴 작업이 도구 시간 제한에 걸리지 않음- 키 없이 LLM 수준 번역을 얻을 수 있는 유일한 방법:
§8.3 sampling은 호스트 모델을 사용하여 번역하며, CLI 프로세스는 호스트 모델에 접근할 수 없음
도구 이름 대조 및 구성 방법은 references/MCP.md를 참조하십시오.
참고:
npx skills add는 이 스킬 디렉토리만 설치하며, MCP 서버는 설치하지 않습니다. 새로 설치할 때는 CLI 경로를 기준으로 합니다.
참고 파일
| 파일 | 내용 |
|---|---|
references/ARCHITECTURE.md | 4단계 파이프라인, 플랫폼 및 백엔드 대체 체인, 설계 제약 사항 |
references/CONFIG.md | 모든 구성 키, 환경 변수, 우선 순위 |
references/MCP.md | MCP 도구 대조표 및 구성 방법 |
references/HOSTS.md | Windows 기본 진입점 및 제한된 호스트 사전 검사 |
assets/config.example.json | 구성 템플릿 |