mcpField
P
podcast-edit

podcast-edit

github.com/openclaudiaクリエイティブ・メディア722260 回インストール1 週間前に更新
リポジトリ

podcast-edit について

未編集の録音を完成したポッドキャスト音声や動画に整えるスキルです。文字起こしに基づくカット、音声補正、完成済みエピソードの部分再編集に対応し、ハイライトも作成できます。

主な機能

  1. 01文字起こしに基づく冒頭と末尾のカット
  2. 02フィラーと無音の除去
  3. 03ノイズ低減と話者ごとの音量調整
  4. 04ポッドキャスト向けラウドネス調整
  5. 05完成済みエピソードの部分再編集
  6. 06ハイライトクリップと短いリールの作成

活用シーン

  1. 01ポッドキャストや会議の録音を仕上げる
  2. 02フィラーや長い無音を取り除く
  3. 03動画を音声版と同じ箇所で編集する
  4. 04エピソードから共有用クリップを作る

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/openclaudia/openclaudia-skills --skill podcast-edit

インストール後、Claude Code で/podcast-editを入力して読み込まれたか確認します。

同梱ファイルfiller_removal.pyvideo_cut.py

詳細

ポッドキャスト編集スキル

ポッドキャスト/会議の未編集録音を、洗練されたポッドキャストエピソードに仕上げます。

機能

  1. スマートトリミング — 文字起こしとイントロ/アウトロの検出により、ポッドキャストの実際の開始位置と終了位置を特定します
  2. フィラーワードの削除 — 嗯、呃、啊、哦、对对对、um、uh などの口癖を削除します
  3. 無音部分のトリミング — 長い無音(>2s)を自然な間(約0.6s)に短縮します
  4. 音声の強化 — ノイズ低減、EQ、複数話者の音量調整、ポッドキャスト標準(−16 LUFS)へのラウドネス正規化
  5. 完成済みエピソードの再編集 — パイプライン全体を再実行せず、すでにレンダリングされたエピソードから指定箇所をピンポイントで削除します
  6. ハイライトクリップとリール — 共有しやすい短い音声を切り出し、音楽付きの約1分間のリールをつなぎ合わせます
  7. 動画の編集 — Zoom/Riverside の動画録画にも同じ編集を適用します(「動画エピソード」を参照)

前提条件

  • ffmpeg と ffprobe がインストールされていること
  • 環境変数に OPENAI_API_KEY が設定されていること(Whisper API による文字起こし用)
  • Python 3 がインストールされていること(標準ライブラリのみ。ヘルパースクリプトに追加の依存関係は不要)
  • オプション:resemblyzer(pip install resemblyzer)— ハイライトリール作成時の話者ダイアライゼーションにのみ使用します

ワークフロー

ステップ 1:音声ファイルを確認する
ffprobe -v quiet -print_format json -show_format -show_streams "INPUT_FILE"

メモ:長さ、サンプルレート、チャンネル数、コーデック、ビットレート。

ステップ 2:ポッドキャストの開始位置と終了位置を特定する(ユーザーが前後のトリミングを指示した場合)

5分間のチャンクに分割し、セグメント単位のタイムスタンプ付きで OpenAI Whisper API を使って文字起こしします。

# Extract chunk
ffmpeg -y -i "INPUT_FILE" -ss OFFSET -t 300 -ar 16000 -ac 1 /tmp/chunk_OFFSET.mp3

# Transcribe
curl -s https://api.openai.com/v1/audio/transcriptions \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -F file="@/tmp/chunk_OFFSET.mp3" \
  -F model="whisper-1" \
  -F response_format="verbose_json" \
  -F language="LANG" \
  -F 'timestamp_granularities[]=segment' > /tmp/transcript_OFFSET.json

文字起こしを確認し、次の表現を探します。

  • 開始の目印:「welcome」「hello everyone」「大家好」「欢迎」、イントロ音楽、最初の本題となる文
  • 終了の目印:「see you next time」「bye」「下期见」「感谢收听」、その後の番組終了後の会話

-ss START -to END と -c copy(再エンコードなし)を使って最初のトリミングを行い、作業用ファイルを作成します。

ステップ 3:フィラーワードを削除する

トリミングしたファイルを5分間のチャンクに分割し、それぞれを単語単位のタイムスタンプ付きで文字起こしします。

# Extract chunks
for i in $(seq 0 300 DURATION); do
  ffmpeg -y -i "TRIMMED_FILE" -ss $i -t 300 -ar 16000 -ac 1 /tmp/wchunk_${i}.mp3
done

# Transcribe each chunk (can run in parallel)
for i in $(seq 0 300 DURATION); do
  curl -s https://api.openai.com/v1/audio/transcriptions \
    -H "Authorization: Bearer $OPENAI_API_KEY" \
    -F file="@/tmp/wchunk_${i}.mp3" \
    -F model="whisper-1" \
    -F response_format="verbose_json" \
    -F language="LANG" \
    -F 'timestamp_granularities[]=word' \
    -F 'timestamp_granularities[]=segment' > /tmp/wtranscript_${i}.json &
done
wait

次に、このスキルに付属するフィラー削除スクリプトを実行します。

python3 ./filler_removal.py \
  --total-duration DURATION \
  --end-at END_TIMESTAMP \
  --cut START1:END1 --cut START2:END2 \
  --chunk-offsets 0,300,600,900,...

引数:

  • --total-duration:トリミングした入力ファイルの長さ(秒)。必須です
  • --end-at:このタイムスタンプ以降をすべてカットします(例:番組終了後の会話が始まる位置)
  • --cut START:END:指定した範囲をカットします。複数回指定できます
  • --chunk-offsets:チャンクのオフセットをカンマ区切りで指定します(デフォルト:0,300,600,…を自動設定)

スクリプトは atrim+concat フィルターを含む /tmp/ffmpeg_filter.txt を出力します。

フィルターを2段階で適用します。

# Step A: Cut fillers → intermediate WAV (avoids re-encoding artifacts)
ffmpeg -y -i "TRIMMED_FILE" \
  -filter_complex_script /tmp/ffmpeg_filter.txt \
  -map '[out]' -c:a pcm_s16le -ar 44100 /tmp/podcast_cut.wav

# Step B: Enhance audio → final MP3
ffmpeg -y -i /tmp/podcast_cut.wav \
  -af "ENHANCEMENT_CHAIN" \
  -c:a libmp3lame -b:a 192k "OUTPUT_FILE"

制限事項: 中国語の単語単位のタイムスタンプでは、隣接する発話に溶け込んだフィラーを Whisper が見落とすことがあります。スクリプトは単独のフィラーを確実に検出しますが、発話に埋め込まれたものは約10~20%見逃す場合があります。

ステップ 4:音声強化フィルターチェーン

デフォルトのチェーン(ゲストに配慮した設定 — 複数話者の音量差に対応)。 過去の実行で最も大きな間違いは、ノイズゲート(agate)を使って音量の小さいゲストの声を完全に消してしまうことです。デフォルトのチェーンに agate を戻してはいけません。

highpass=f=80,                                    # Remove room rumble
lowpass=f=12000,                                  # Remove hiss (use 7500 for 16kHz sources)
afftdn=nf=-25:nr=8:nt=w,                         # Gentle FFT noise reduction
equalizer=f=180:t=q:w=1.5:g=-2,                  # Cut mud
equalizer=f=2500:t=q:w=1.2:g=3,                  # Boost presence
equalizer=f=4500:t=q:w=1.5:g=1.5,                # Boost clarity
dynaudnorm=f=200:g=5:p=0.95:m=5:s=0,             # Rolling-window normalization — lifts the quieter speaker independently
acompressor=threshold=-20dB:ratio=2:attack=5:release=200:makeup=1,  # Gentle glue
loudnorm=I=-16:TP=-1.5:LRA=13                    # Podcast standard loudness

dynaudnorm が重要な理由: 200 ms のローリングウィンドウ単位で正規化するため、ゲストが話しているときは、そのウィンドウの音量がホストの大きな音量のウィンドウとは独立して引き上げられます。順序が重要です。コンプレッサーがバランスの取れた信号を処理できるよう、acompressor の前に dynaudnorm を実行してください。

デフォルトのチェーンに次のフィルターを追加してはいけません。

  • agate(ノイズゲート)— しきい値より音量の小さい話者の声をすべてカットし、ゲストの声が消えてしまいます。
  • 強いコンプレッション(比率 >3:1、メイクアップゲイン >2 dB)— ダイナミクスを平坦化し、ゲストの声が不自然にポンピングしたように聞こえます。
  • loudnorm の狭い LRA(<12)— 自然な発話のダイナミクスを潰してしまいます。

ソースのサンプルレートに合わせてローパスを調整します。

  • 16kHz のソース → lowpass=7500
  • 44.1kHz 以上のソース → lowpass=12000(または省略)

レンダリング後にゲストの声が聞こえることを確認します。 ffmpeg -i OUTPUT -af "ebur128=peak=true" -f null - を実行し、I: が −16 LUFS 付近、LRA: が4~6 LU であることを確認します(dynaudnorm が先にウィンドウ単位でバランスを調整しているため、LRA がより狭くても問題ありません)。出力音声でゲストの声が消えているようなら、ノイズゲートや強すぎるコンプレッサーが再び混入していないか確認してください。

ステップ 5: 出力を検証する
ls -lh "OUTPUT_FILE"
ffprobe -v quiet -show_entries format=duration -of csv=p=0 "OUTPUT_FILE"

報告: 所要時間、ファイルサイズ、削除された内容(フィラー数、無音数、節約できた時間)。

動画エピソード(Zoom / Riverside の録画)

ソースが動画で、ユーザーがカット済みの動画を求めている場合(たとえば、共同ホストが編集済みエピソードを別の言語に吹き替えるために必要とする場合)は、上記とまったく同じようにステップ 1~3 を実行します。-vn を使って mp4 から音声チャンクを直接取り出し、同じカットポイントを映像と音声に 1 パスで適用します:

# 1) same chunks + transcription as Step 3, but sourced from the video
for i in $(seq 0 300 DURATION); do
  ffmpeg -y -v error -ss $i -t 300 -i SOURCE.mp4 -vn -ar 16000 -ac 1 /tmp/wchunk_${i}.mp3 &
done; wait

# 2) filler_removal.py as usual -> /tmp/ffmpeg_filter.txt

# 3) turn its keep segments into a combined video+audio filter
python3 video_cut.py /tmp/video_filter.txt

# 4) one render pass (hardware encoder; ~7 min for a 60-min 1080p episode)
ffmpeg -y -i SOURCE.mp4 -filter_complex_script /tmp/video_filter.txt \
  -map '[vout]' -map '[aout]' \
  -c:v h264_videotoolbox -b:v 3500k -c:a aac -b:a 160k \
  -movflags +faststart episode-edited.mp4

Apple 以外のハードウェアでは、h264_videotoolbox の代わりに -c:v libx264 -crf 21 -preset veryfast を使用してください。

注意:

  • --chunk-offsets は $(seq 0 300 3600 | paste -sd, -) のように組み立ててください。 末尾に空のフィールドがあると、引数パーサーがクラッシュします。
  • 結果はジャンプカット形式になります。これは想定どおりであり、トーキングヘッドのグリッドでは問題ありません。400 以上のカットポイントで短いディゾルブを入れると、ハードカットよりも見劣りします。
  • video_cut.py は強化チェーンを同じパスに組み込むため、音声の経路とは異なり、2 パスの WAV 中間ファイルはありません。その後でチェーンを再度実行しないでください。
  • 60 分の 1080p 出力には約 1.5 GB を見込んでください。メールで送るには大きすぎるため、アップロードしてリンクを共有してください。
  • keep セグメントのリストはエピソードの隣に保存してください。 これがないと、後で「同じカットで、ただし動画として」というリクエストが来たときにカットを再導出する必要があり、すでに納品した音声版と一致しなくなります。

出力の規約

  • フォーマット: MP3、192 kbps、モノラル(ソースがステレオで各チャンネルに別の話者がいる場合を除く)
  • ラウドネス: −16 LUFS(ポッドキャスト標準)
  • 常に 2 パス: まず WAV にカットし、次に MP3 へ強化する

すでに完成したエピソードを再カットする

ユーザーが公開済みエピソードの特定の問題を指摘した場合(「いくつかの文が残っている」「X についての部分をカットして」「エンディングが録り直された」「重複したイントロを削除して」)、生データからパイプライン全体を再実行しないでください。 完成した MP3 から問題のある範囲を外科的にカットし、一度だけ再エンコードします:

  1. 最終ファイルを 5 分のチャンクで再文字起こしします(セグメント単位)→ 絶対タイムスタンプ付きの統一された文字起こしが得られます。これがあなたの地図です。
  2. 指摘された各項目について、それを含むチャンクだけの単語レベルのタイムスタンプを取得します(これらのフレーズは通常、セグメントの境界ではなく文中に埋め込まれています)。厳密なイン/アウトポイントを設定します。
  3. カット範囲以外のすべてを保持する 1 つの atrim+concat フィルターを構築し、WAV(pcm_s16le)にレンダリングしてから、1 回の MP3 パスを行います。強化チェーンを再適用しないでください — 最終版はすでに強化されラウドネス正規化されているため、再実行すると二重処理になります。
  4. すべての接続点を検証します: 各新しい結合点(新しいタイムライン内)を中心に約 11 秒のウィンドウを抽出し、再文字起こしします。不正な音声が消え、再接続がクリーンに読めることを確認します。
  5. ショーノートのタイムラインを再計算します: カット後のすべてのタイムスタンプは、その前にあるすべてのカットの合計長だけ前にシフトします。公開ファイルの先頭にハイライトリールが付いている場合は、リールの長さもオフセットとして考慮してください(再カットされたリールは長さが変わるため、エピソード全体がシフトします)。
再カットチェックリスト — 最初のパスでよく残ってしまうもの

これらは実際の文に溶け込んでいるため、フィラー/無音の除去をすり抜けます。文字起こしを明示的にスキャンして探してください:

  • 会議/技術的な雑談: 「ミュートされています / ミュート解除して」、「你声音太小 / 听得到吗」、「画面が見えますか」、「ちょっと待って確認します」。フレーズをカットし、周囲のコンテンツは残します。
  • 行き止まりのトピック: パネリストが誰も調べていない製品/事例を持ち出し、その後「我们就跳过吧 / スキップしましょう」と言う — スキップの行だけでなく、脱線全体をカットします。
  • 録り直されたセグメント(特にエンディング): 雑なファーストテイクの後、「重新开始 / 从头来 / やり直そう / 冗長に感じる」のようなマーカーがあり、その後にクリーンな再テイクが続きます。失敗したテイクをカットし、録り直しを残します。必ず最後の約 3 分間を確認してください。
  • 本番前/重複したイントロ: 公式開始前に録音された自己紹介が、後で繰り返される — 本番前のコピーをカットします。
Whisper API の不安定さ

並列の単語レベル呼び出しがときどき空(0 バイト)を返すことがあります。空のものは呼び出しの間に sleep 1 を入れて順番に再試行してください。

ハイライトクリップと1分間のリール

完成したエピソードから、共有しやすい短い名言クリップ(意見の分かれる瞬間や洞察に満ちた瞬間)を切り出し、必要に応じて音楽とつないで約1分間のリールにします。

名言クリップの選び方
  • 各クリップは2文、約8~20秒を目安にします。意見が分かれる、意外性がある、または引用したくなるセリフを優先します。
  • **ホストも含め、すべての話者を必ず入れてください。**複数ゲストのパネルでは、最もよく話す1~2人だけのリールにならないようにします。編集を始める前に、参加者全員から少なくとも1つは印象的なクリップを選び、話者の特定を確認してください。(これが一番よくある間違いです。実際は1人だけの「ハイライト」になってしまいます。)**進行役/ホストは、主に質問をするため最も漏れやすい存在です。**引用したくなるホストのセリフ(リアクション、ジョーク、鋭い切り口など)を見つけて、必ず含めてください。
  • **文字起こしのテキストから話者を特定することはできません。試みたり、ユーザーに特定を頼んだりしないでください。**Whisper が出力するのは発言内容であり、誰が話したかではありません。言い回しから話者を推測してもうまくいきません(ホストらしく見えるセリフを実際に言ったのはゲスト、ということもよくあります)。リールに特定の人物を入れる必要がある場合は、音声のダイアライゼーションを行ってください(下記の手順)。話者を推測ではなく測定で特定できます。
  • リールの流れ(つかみ → … → 印象的な締め)を考えて順序を決め、同じ話者のクリップを連続させないでください。
誰が話しているかを特定する — 話者ダイアライゼーション(resemblyzer)

特定の人物のクリップが必要な場合(またはユーザーから「Xがリールに入っていない」と言われた場合)は、文字起こしを読むのではなく、声で特定します。pip install resemblyzer(エンコーダーが同梱されているため、HF トークンは不要です)。5人のパネルでうまくいった手順は次のとおりです。

  1. **特定できる人全員の、明瞭な参照音声を作成します。**自分の名前を言う区間(自己紹介)や、自分の製品を紹介する区間(最後の告知など)を使います。これらは確実に1人だけが話している区間です。安定性を高めるため、1人につき2~3区間の平均を取ります。enc.embed_utterance(preprocess_wav(slice, source_sr=16000))を実行し、平均を取り、L2 正規化します。
  2. **エピソード全体を無条件にクラスタリングしないでください。**Whisper のセグメントにはクロストークが含まれるため、AgglomerativeClusteringでは、すべてが1つの巨大なまとまりと単独のセグメントに分かれてしまいます。代わりに、各セグメントの埋め込み(コサイン類似度)を、明瞭な参照音声すべてと照合します。どの参照音声にも十分一致しないセグメント(実際に一致するものの類似度が0.88~0.94なのに、最高類似度が≲0.78)は、特定できていないN人目の話者です。
  3. **同じ一貫した声かどうかを確認します。**類似度の低いセグメント同士が十分に似ていること(≳0.87)、かつ、既知の各参照音声とは全体として異なることを確認します。それらから参照音声を作成し、すべてのセグメントを再評価します。信頼度の高い一致はすべてその人物のものになるはずです。
  4. **既知の音声と照合して妥当性を確認します。**特定済みのクリップ(例:誰かが製品を紹介する区間)は、その人物自身の参照音声との類似度が最も高くなる必要があります(≳0.9)。参照音声を分離できない場合は、区間を長くし、平均する数を増やしてください。

エピソード全体を一度だけ、ffmpeg パイプ(-f f32le -)を使って16 kHzのモノラル float として読み込み、メモリ内で切り出します。セグメントごとに ffmpeg を実行するよりはるかに高速です。

切り出す前に確認する(必須)

候補ごとに対象区間を抽出し、再度文字起こしを行って、(a)内容と話者が正しいこと、(b)文の区切りが明瞭なことを確認します。Whisper は名前を誤認識するため、最初の文字起こしの表記を決してそのまま信頼しないでください。単語単位の細かさで確認し、最初の単語が切れない開始位置と、言いよどみや繰り返しを除いた終了位置を決めます。

時間を無駄にする2つの落とし穴
  • **-ss/-toは入力オプション(-iより前)にする必要があります。**出力オプションにすると、無音になったり、範囲が間違ったりします。ffmpeg -ss START -to END -i in.mp3 ...
  • zsh の配列は1始まりです。for s in "${SEG[@]}"(値を反復処理)を使い、i=0から${SEG[$i]}を使うことは避けてください。
  • マスター作成後にエピソードが編集(冒頭部分や低音質部分のカット)された場合は、編集済みファイルからタイムスタンプをずらして音声を切り出します(各カット地点より前に削除された秒数を差し引きます)。
クリップを1つ作成する(無音部分を除去し、フェードイン/フェードアウトを調整)
# 1) extract + remove pauses (collapse gaps >0.2s; gaps sit near -25dB after dynaudnorm, so threshold ~-23dB)
ffmpeg -y -ss START -to END -i FINAL.mp3 -ar 44100 -ac 1 \
  -af "silenceremove=start_periods=1:start_silence=0.04:start_threshold=-30dB:stop_periods=-1:stop_duration=0.20:stop_threshold=-23dB:detection=peak" sr.wav
# 2) speech fades (compute fade-out start from sr.wav duration)
ffmpeg -y -i sr.wav -af "afade=t=in:st=0:d=0.12,afade=t=out:st=${DUR-0.3}:d=0.3" f.wav
# 3) tune in -> speech -> tune out
ffmpeg -y -i sting_in.wav -i f.wav -i sting_out.wav \
  -filter_complex "[0][1]acrossfade=d=0.18:c1=tri:c2=tri[a];[a][2]acrossfade=d=0.18:c1=tri:c2=tri[out]" \
  -map "[out]" -c:a libmp3lame -b:a 192k clip.mp3

スティング音を合成します(音声素材は不要です)。柔らかいベルの和音を、低い音量で使います。

# tune-in: bright C-E-G bell
ffmpeg -y -f lavfi -i "sine=f=523.25:d=0.85" -f lavfi -i "sine=f=659.25:d=0.85" -f lavfi -i "sine=f=783.99:d=0.85" \
  -filter_complex "[0][1][2]amix=inputs=3:normalize=1,afade=t=in:st=0:d=0.02,afade=t=out:st=0.2:d=0.65,lowpass=f=3800,volume=0.30[s]" -map "[s]" -ar 44100 -ac 1 sting_in.wav
# tune-out: lower, gentler G-C bell
ffmpeg -y -f lavfi -i "sine=f=392:d=0.75" -f lavfi -i "sine=f=523.25:d=0.75" \
  -filter_complex "[0][1]amix=inputs=2:normalize=1,afade=t=in:st=0:d=0.06,afade=t=out:st=0.15:d=0.6,lowpass=f=3200,volume=0.22[s]" -map "[s]" -ar 44100 -ac 1 sting_out.wav
1 分間のリール(連結+音楽+フェードイン/アウト)

無音部分をトリミングした音声セグメント(冒頭と末尾に 1.5 秒の無音、セグメント間に約 0.35 秒の間隔)を、concat デマルチプレクサで連結します。その後、柔らかなシンセパッドを下にミックスし、全体をフェードイン/アウトします。リール内でクリップごとの短いジングルは使い回さないでください。全体に 1 回だけフェードをかけるほうがすっきりします。

# music bed: warm 4-chord pad (C-G-Am-F), each chord 4s, lowpass+tremolo, concat -> pad16.wav, then loop
# (mkchord mixes 3 sines, normalize=1, lowpass=f=750, tremolo=f=4.5:d=0.25, afade in/out)
ffmpeg -y -i speech_reel.wav -stream_loop 6 -i pad16.wav \
  -filter_complex "[1]atrim=0:${TOT},volume=0.075[m];[0][m]amix=inputs=2:normalize=0:duration=first[mix];[mix]afade=t=in:st=0:d=1.3,afade=t=out:st=${TOT-1.6}:d=1.6[out]" \
  -map "[out]" -c:a libmp3lame -b:a 192k highlight.mp3
  • パッドの音量を約 0.075 にすると、音声を十分に優勢に保てます(最終ミックスを再度文字起こしして確認し、すべてのセリフが明瞭に認識されるようにしてください)。amix … normalize=0 を指定し、音声がダッキングされないようにします。
  • 目標は同じ −16 LUFS です。音楽によって音量が約 −16.5 を超えないようにしてください。
出力レイアウト
  • 個別クリップ:episodes/ep{NNN}/highlights/ep{NNN}-clip{N}-{who}.mp3
  • 単一のリール:episodes/ep{NNN}/ep{NNN}-highlight.mp3

カバーアートの生成(任意)

OpenAI GPT Image API(gpt-image-1)を使って、番組独自のスタイルに合わせたエピソードのカバーアートを生成します。自分で用意したスタイル参照画像(過去のカバー、ワードマーク、配色など)を渡すと、モデルがそれを模倣します。

import openai, base64

client = openai.OpenAI()  # uses OPENAI_API_KEY from env
style_img = open("YOUR_STYLE_REFERENCE.png", "rb")

result = client.images.edit(
    model="gpt-image-1",
    image=[style_img],                       # add a content reference as a 2nd image if you have one
    prompt="""Create an illustration in the EXACT same art style as this image
(match the line work, color palette, background, and decorative elements).
Depict: [DESCRIBE THE SCENE]. Keep [YOUR SHOW NAME / wordmark] in the same
style and position as the reference.""",
    size="1024x1024",
)
with open("cover.png", "wb") as f:
    f.write(base64.b64decode(result.data[0].b64_json))

注意:環境から OPENAI_API_KEY を読み込み、1024×1024 の PNG を出力し、エピソードを通して番組のワードマークやブランディングに一貫性を保ちます。

番組ノート — バイリンガルでの執筆(該当する場合)

ホストが中国語/英語のバイリンガル番組ノートを作成する場合、中国語のセクションは実際の中国語で書く必要があります。英語の動詞や名詞を混ぜた中国語風の文法ではいけません。「close 了一个 deal」「build 出来的 agent」「PR 不是 buy 来的」のようなコードスイッチングは下書きのように読めるため、最も避けるべき間違いです。

翻訳ルール

以下のスタートアップ/テック分野でよく使われる英語の借用語を中国語に翻訳してください。

  • close deal → 订单成交 / 达成交易 / 签下订单
  • build(製品を)→ 搭建 / 做出 / 打造
  • integration → 集成
  • view(動画/ページの閲覧数)→ 播放 / 浏览
  • stack(技術スタック)→ 体系 / 技术栈
  • category leader → 品类领导者
  • front-end / front end(製品の意味)→ 外壳 / 前端
  • success story → 客户案例 / 成功故事
  • SMB → 中小企业
  • Enterprise(セグメント)→ 大型企业 / 企业级
  • aha moment → 顿悟时刻
  • onboarding → 上手 / 入门
  • retention → 留存
  • churn → 流失
  • pipeline → 销售漏斗 / 业务线
中国語の文章内でも英語のままにするもの
  • ブランド名と製品名 — 企業名/製品名/人名はそのままにします
  • 非常によく使われるスタートアップの略語 — CEO、CTO、CMO、PMF、ARR、MRR、PR、AI、AI Agent、SaaS、API
  • 数値が先頭に付く通貨表記 — $20K、$200K、または 200 美金(数値と組み合わせる場合はどちらの形式でもかまいません)
仕上げる前に

中国語の読者になったつもりで、中国語のセクションを読み直してください。「build」「close」「deal」「view」「stack」「leader」などが単独の英単語として含まれているなど、文が中途半端に翻訳されていると感じる場合は、その語を中国語に書き換えてください。読み直したときに英語のまま残っているべきなのは、ブランド名と上記の略語だけです。

名前の確認(非常に重要)

Whisper は企業名、製品名、人名を頻繁に誤認識します。番組ノートや、名前とリンクを含む出力を作成する前に、次の手順を実行してください。

  1. 文字起こし後、すべての固有名詞を抽出します — 企業名、製品名、人名、言及された URL。
  2. ユーザーに確認・修正を依頼します — Whisper はブランド名について、似た音の別の語を聞き取ることがあります。
  3. 文字起こしされた名前から URL を推測してはいけません — 「Acme」のように聞こえる名前でも、acme.com、acmehq.com、その他の可能性があります。必ず確認してください。
  4. 番組ノート、タイトル、エピソードのメタデータ、すべての出力で、確認済みの名前を一貫して使用します。

バックリンクやソーシャル投稿を作成する場合は特に重要です。ドメインのスペルを間違えると、リンクが無駄になります。

番組ノートの構成(推奨)

2つのセクションに分けます。先に中国語、その後に英語(または番組の対象言語)を記載してください。交互に並べたり、横並びにしたりしないでください。

見出しのルール: 見出しは浅く、統一してください。見出しレベルを1つ選び(例:H2)、すべてのサブセクションをそのレベルにそろえます。公開プラットフォームによっては、1つの見出しレベルと太字しか表示されないものもあります。その場合は、それに合わせてください。

タイムスタンプの形式: 常に先頭にゼロを付けた MM:SS 形式にしてください(例:08:25、00:00、42:10)。0:00 や 1:05 は使用しないでください。

EP{NNN}: {Episode title}

---

## 中文

**嘉宾:** {中文姓名 English Name}, {中文职位} {公司} (URL)

## 简介
{完整中文段落}

## 时间轴
- 00:00 — {中文描述}
- 08:25 — {中文描述}

## 核心要点
- {中文要点}

## 相关链接
- {品牌名}:{URL}

---

## English

**Guest:** {English Name}, {Title} at {Company} (URL)

## Summary
{Full English paragraph}

## Timestamps
- 00:00 — {English description}
- 08:25 — {English description}

## Key Takeaways
- {English takeaway}

## Links
- {Brand}: {URL}

箇条書きを2言語併記にするのではなく、セクションを2つに分ける理由: 中国語の読者には読みやすい中国語の文章を、英語の読者には読みやすい英語の文章を届けられます。箇条書きごとに「中文 / English」と交互に書くと、どちらの言語も読みづらくなります。それぞれのセクションだけで完結するように書いてください。

アーカイブと命名規則(推奨)

各エピソードを個別のフォルダーにまとめ、単独で完結するようにします。シンプルなゼロ埋めのレイアウトなら、規模が大きくなっても整理しやすくなります。

episodes/
├── ep001/
│   ├── ep001-final.mp3      # the finished episode
│   ├── ep001-highlight.mp3  # optional 1-min reel
│   ├── cover.png
│   └── shownotes.md
└── ep002/
    └── ...
  • ディレクトリ:ep{NNN}(3桁のゼロ埋め)
  • 音声:ep{NNN}-final.mp3。ハイライトクリップは ep{NNN}/highlights/ep{NNN}-clip{N}-{who}.mp3 に保存します
  • エピソードのタイトル:読者の興味を引く、内容が伝わるタイトルを先頭に付けます(トピックを述べるだけではなく、読者を引き込みましょう)。

簡単なトリミング(無音部分の削除なし)

ユーザーが単純なトリミング(例:「最初の3秒をカット」)だけを希望する場合:

ffmpeg -y -i "INPUT" -ss 3 -c copy "OUTPUT"

音声処理が不要な場合は、瞬時に無劣化でトリミングできる -c copy を使用してください。

コメント