Communitygithub.com

RolynTrotter/vibe-podcast

소스 자료(YouTube 강연, 강의, 지난 에피소드)에서 인용 가능한 발췌문을 추출하여 타임스탬프가 포함된 클립과 팟캐스트용 인용 하단 자막(로우어 서드)을 생성합니다. 소스 영상 트랜스크립션, 특정 주제 발언 검색, 에피소드용 인용문이나 클립 추출, 강연 또는 강의에서 인용/로우어 서드 생성이 필요할 때 사용하세요.

vibe-podcast란 무엇인가요?

이 기술은 팟캐스트 제작자가 YouTube 강연, 토크, 자체 과거 에피소드 등 다양한 소스 자료에서 인용 가능한 발췌문을 효율적으로 발굴하고, 이를 타임스탬프가 포함된 클립과 함께 사용할 수 있도록 가공하는 워크플로우를 제공합니다. 주로 Claude Code와 같은 AI 에이전트 환경에서 사용되며, `citekit.py`라는 파이썬 기반 도구를 통해 트랜스크립션, 인용문 검색, 클립 생성, FCP(파이널 컷 프로)용 로우어 서드 템플릿 생성을 자동화합니다. `mlx-whisper`를 사용하여 고속 로컬 트랜스크립션을 수행하며, 잘못 인식된 부분을 수동으로 수정할 수 있는 `fix` 명령어를 제공하여 정확성을 높입니다. 최종적으로는 에피소드 편집 시점에 맞춰 삽입할 클립과 인용 하단 자막 큐(로우어 서드)를 생성하여, AI 에이전트가 팟캐스트 제작 과정에서 인용문 기반 편집을 자동화할 수 있도록 지원합니다.

지원 대상~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/RolynTrotter/vibe-podcast/tree/HEAD/.claude/skills/citations

즐겨 사용하는 AI에게 물어보기

이 에이전트 스킬이 미리 로드된 새 채팅을 엽니다.

문서

인용문: 소스 → 트랜스크립트 → 인용문 → 큐 및 클립

도구: agent-citations/citekit.py (stdlib Python + mlx_whisper 및 ffmpeg). 입력 파일을 절대 덮어쓰지 않으며, --force 없이는 자체 출력 파일을 교체하지 않습니다.

배치 레이아웃

active_edits/<subject>/ 아래 주제별 폴더:

sources/video_sources.txt          사용자의 URL 목록
sources/audio/<id>.m4a .info.json  yt-dlp에서 다운로드 (1단계)
sources/transcripts/<id>.json .md  2단계
podcast/<ep>.json .md              자체 에피소드 캡션, 가져오기 (2b단계)
sources/quotes.json                3단계, 사용자가 작성
sources/citations/                 4단계 출력 파일

1. 다운로드 (사용자가 직접 실행)

여기서 YouTube는 익명 yt-dlp를 차단합니다. 사용자에게 실행 명령어를 직접 제공하지 말고 아래 명령어를 알려주세요. Firefox 쿠키와 tv/safari 클라이언트가 필요하며, 오디오 크기를 작게 유지합니다 (Whisper는 16kHz 모노만 필요):

cd active_edits/<subject>/sources && for id in ID1 ID2; do yt-dlp --cookies-from-browser firefox --extractor-args "youtube:player_client=tv,web_safari,mweb" -f "wa/w" -x --audio-format m4a --postprocessor-args "ExtractAudio:-ac 1 -ar 16000" --write-info-json --write-auto-subs --sub-langs en --sub-format json3 --no-overwrites -o "audio/%(id)s.%(ext)s" "https://youtu.be/$id"; done

채널의 전체 영상을 처리하려면 먼저 목록을 확인한 후 선택하세요: yt-dlp --flat-playlist --print "%(id)s %(duration_string)s %(title)s" https://www.youtube.com/@CHANNEL/videos. 목록이 길면 Jev (vibe-classification)로 제목을 분류하세요.

2. 트랜스크립션

  • citekit.py transcribe sources/audio/<id>.m4a: mlx-whisper large-v3-turbo 모델, 단어 단위 타임스탬프. 초기 프롬프트는 동영상 제목과 설명이며, 대부분의 이름 철자를 수정합니다. 이 Mac에서 실시간의 약 85배 속도로 실행됨 (15분 분량에 약 35초 소요; 모델은 한 번 다운로드).
  • citekit.py captions sources/audio/<id>.en.json3: YouTube 자동 캡션. 즉시 처리되지만 구두점이 없음. tv 클라이언트는 종종 자동 캡션을 저장하지 않습니다.
  • 2b. 자체 에피소드: citekit.py itt EP.itt --id podcastN --media EP.mp4 --out active_edits/<subject>/podcast --fix 'REGEX=>Right'. FCP(Final Cut Pro) 캡션은 이름을 망가뜨립니다. 에피소드 1의 경우: --fix '\bver ?m+[iu]l+e?\b=>Vermeule' --fix '\bvermil\b=>Vermeule' --fix '\bAsian Vermeule=>Adrian Vermeule'. 에피소드 1에는 podcast/podcast1.fixes.json에 기록된 단어 수준 수정 사항이 있으며 (Schmidt→Schmitt 등), 재가져오기 시 재적용됩니다.

발견 즉시 오인식 수정 (질문하지 말고)

확실한 오청음(이름, 잘못된 인용문, Whisper가 두 번 인식한 말 더듬기 등)을 발견하면 수정하세요: citekit.py fix TRANSCRIPT 'old words=>new words' [...] [--near SECONDS]. 이 명령어는 <id>.json/.md 파일을 직접 수정하며 (새 단어는 기존 구간의 타이밍을 공유하고, 일치는 세그먼트 경계를 넘을 수 있으며, 후행 구두점은 유지됨), 수정되지 않은 원본 출력을 <id>.raw.json으로 보관하고 모든 수정 사항을 <id>.fixes.json에 기록합니다. transcribe와 itt는 이 로그를 재생하므로 재실행 시 수정 사항이 유지됩니다. 확실하지 않은 경우? 추측 대신 해당 지점을 다시 들어보세요: ffmpeg -ss T -to T2 -i audio.m4a x.wav && mlx_whisper x.wav --output-format txt. 먼저 수정한 후, 수정된 단어를 인용하세요: locate는 트랜스크립트에서 일치를 찾습니다.

3. 인용문 발굴 (사용자 판단)

  1. 에피소드 트랜스크립트가 있다면 읽고, 호스트들이 주제에 대해 언급한 주장을 각각 에피소드 타임코드와 함께 나열하세요. 이 순간들이 클립으로 뒷받침하거나 반박할 수 있는 지점입니다.
  2. 각 주장에 대해 citekit.py search 'regex' sources/transcripts/ 명령어로 후보를 찾은 후, 일치 지점 주변의 .md 파일을 읽으세요. 전체 강의도 읽으세요. 가장 좋은 인용문이 호스트들이 언급한 지점과 항상 일치하는 것은 아닙니다.
  3. 좋은 인용문은 짧고(5–25초 분량), 자체적으로 완결되며, 화자 자신의 입장을 명확히 나타내고(상대방 의견 요약이 아닌), 하단 자막(로우어 서드)에 인용하기 적합해야 합니다. 트랜스크립트의 정확한 단어를 유지하세요. 정리하지 마세요. 그렇지 않으면 locate가 찾을 수 없습니다.
  4. sources/quotes.json 작성:
{"project": "Ep1 Vermeule citations", "fps": 29.97, "episode": "../podcast/podcast1.json",
 "quotes": [{"id": "publius-weak-exec", "source": "Bw9M01S8MFI", "approx": 1234,
   "text": "트랜스크립트의 정확한 단어",
   "episode_at": 2575, "episode_context": "호스트들이 해밀턴과 로마 독재관에 대해 논의",
   "why": "그의 주제 진술 자체", "tags": ["executive", "Federalist"],
   "citation": {"author": "~Adrian Vermeule", "title": "The Publius Paradox", "date": "5 Jun, 2018",
                "publication": "Chorley Lecture, LSE"}}]}

episode (quotes.json 기준 상대 경로)는 우리 에피소드의 트랜스크립트입니다. 이와 함께 각 인용문의 episode_at (호스트들이 해당 지점을 언급하는 대략적 시간)은 삽입 지점이 됩니다: 그 시점에 재생 중인 호스트 문장의 끝 부분입니다. 전체 생각을 인용하세요. 다음 문장이 이미지나 주장을 완성한다면 포함하세요 (5–25초 클립이 목표이지 엄격한 제한이 아닙니다).

citation의 기본값은 동영상 제목, 업로드 날짜 및 채널입니다. 실제 강연 장소와 날짜(설명에서)는 최상위 레벨 "sources": {"<id>": {"citation": {...}}}에 한 번만 입력하세요. 인용문 자체의 citation은 이를 재정의합니다. 저자 이름에는 쇼의 ~ 접두사를 붙이고, \n은 긴 제목을 두 줄로 나눕니다.

그가 인용하는 내용(해밀턴, 카프카, 법학대전 등)은 원문과 대조 확인하세요. Whisper는 그럴듯한 잘못된 단어를 듣습니다: Publius 강의에서 Kafka의 "sacrificial pitchers"를 "pictures"로 인식했습니다.

4. 큐와 클립

citekit.py cues sources/quotes.json은 각 인용문을 단어 타임스탬프에 스냅하고(퍼지 매칭; 일치 점수가 < 0.8이면 경고) sources/citations/에 다음 파일을 작성합니다:

파일용도
citations.md에피소드 순서대로 검토 시트: 삽입 시간 (기록 시간 및 이전 삽입 후), 컷 직전 호스트의 말, 인용문, 소스/클립 시간, YouTube ?t= 링크
clips.json에이전트 편집용: 소스 in/out, 패딩 in/out (기본 각 면 5초, --pad-before/--pad-after, 인용문별 pad_before/pad_after), insert_at, insert_at_after_earlier_inserts, insert_after
citation_cues.jsonagent-motion/titles_fcpxml.py용: 인용 v2 로우어 서드가 클립이 삽입된 에피소드의 타임라인에 맞춰, 화자가 말을 시작할 때 표시되도록 타이밍 조정. 배치되지 않은 인용문은 연속적으로 배치
download_clips.sh사용자가 실행: 해당 패딩 범위만 고화질 비디오 다운로드 (--download-sections)

그런 다음 citekit.py audio-clips sources/citations/clips.json은 로컬 오디오에서 패딩된 오디오 미리보기를 잘라내어 귀로 확인할 수 있게 합니다. FCP에서 로우어 서드를 배치하려면 motion-graphics 기술을 따르세요: python3 agent-motion/titles_fcpxml.py sources/citations/citation_cues.json -o citations.fcpxml.

참고 사항

  • transcribe는 자체적으로 16kHz WAV로 디코딩하며, 오디오가 비디오보다 훨씬 짧게 디코딩되면 거부합니다. 다른 -f 옵션으로 재개된 yt-dlp 다운로드는 두 코덱을 하나의 .m4a에 결합하며 (2026-10-18 확인: AAC-LC 다음 HE-AAC), ffmpeg는 전환 이후의 모든 것을 자동으로 삭제합니다. --no-continue로 다시 다운로드하세요. 포맷 변경 시 절대 재개하지 마세요.

  • 클립을 귀로 확인하거나 저렴하게 확인하세요: mlx_whisper citations/audio_clips/<id>.m4a --output-format txt를 실행하면 인용문과 몇 초의 리드인 및 테일이 표시됩니다.

  • Whisper 타임스탬프는 단어 수준에서 약 ±0.3초 정확도입니다. 그래서 클립 패딩이 존재합니다. FCP iTT 캡션은 전체 줄만 시간을 지정하므로, itt는 단어를 각 줄에 균등하게 분산합니다.

  • Wispr Flow 커넥터는 Meeting Recorder 트랜스크립트만 읽습니다. 파일을 트랜스크립션할 수 없습니다.

관련 스킬