Skip to main content
Glama

ossicle

Deepgram を使ってローカルメディアファイルと URL を文字起こしする、Claude Code 用 MCP サーバー、およびスタンドアロン CLI です。文字起こし結果は Markdown としてディスクに書き出され、大きなデータがインラインで返されることは決してありません。

すべてのジョブは、何かを送信する前に、測定された再生時間に基づいて料金が算出されます。見積もりが設定済みのジョブあたり上限を超えるジョブは、即座に拒否されます。このガードこそが、このパッケージの要点です。

要件

  • Node >= 20

  • PATH 上の ffprobe と ffmpeg(再生時間の計測と 16 kHz モノラル opus のアップロード用)

  • URL 入力を利用する場合は、PATH 上の yt-dlp

  • Deepgram API キー

Related MCP server: whipscribe-mcp

インストール

npm install
npm run build
cp .env.example .env    # then fill in DEEPGRAM_API_KEY

設定

設定は、パッケージルートの .env ファイルのみから読み取られます。シェルにエクスポートされた変数と claude mcp add --env フラグは意図的に無視されるため、どのプロジェクトから起動された場合でも、サーバーは同じように動作します。

変数

必須

デフォルト

意味

DEEPGRAM_API_KEY

はい

Deepgram API キー

DEEPGRAM_MODEL

いいえ

nova-3

文字起こしモデル

DEEPGRAM_USD_PER_MINUTE

いいえ

0.0043

音声 1 分あたりの価格。見積もりに使用

MAX_COST_PER_JOB_USD

いいえ

1.00

ジョブあたりの厳格な上限。超えた場合は拒否となり、確認を求めることはありません

TRANSCRIPTION_OUTPUT_DIR

いいえ

./output

ジョブフォルダの書き出し先。相対パスはパッケージルートを基準に解決されます

OPENROUTER_API_KEY

整形時のみ

整形パスのためのキー。文字起こしには不要です

OPENROUTER_MODEL

いいえ

openai/gpt-4o-mini

整形パスが構造を問い合わせるモデル

FORMAT_HEADINGS_MIN_SENTENCES

いいえ

120

この文数未満の場合、整形はパラグラフとタグのみを追加し、セクションは追加しません

MCP サーバー

claude mcp add ossicle -- node "<absolute path to this repo>/dist/index.js"

transcribe

入力

型

デフォルト

備考

source

文字列

必須

ローカルファイルのパス、または yt-dlp が取得できる任意の URL

diarize

ブール値

false

実験的。 話者をラベル付けした ## Speaker N [mm:ss] ブロック

model

文字列

設定済みモデル

Deepgram モデルの上書き

language

文字列

en

音声言語コード

force

ブール値

false

キャッシュヒット時も再文字起こしします。再度費用がかかります

戻り値は、文字起こしパス、ジョブフォルダ、再生時間、推定 USD と実際に消費した USD、cached フラグ、500 文字に制限されたプレビューです。完全な文字起こしはディスク上に残ります。

話者分離

話者分離は実験的であり、デフォルトではオフです。実際の録音では、Deepgram が発言の話者を誤認することが非常に多いため、話者ラベル付きの出力はプレーンなパラグラフよりも読みにくくなります。そのため、このフラグは通常のオプションとして推奨されるのではなく、話者分離がそのリスクに見合うケースのために残されています。話者分離はキャッシュキーの一部であり続けるため、フラグを切り替えても古い文字起こしが返されることはありません。

format_transcript

入力

型

デフォルト

備考

target

文字列

必須

transcribe の結果の job_dir、または元のローカルファイルパス

force

ブール値

false

構造をモデルに再依頼します。再度費用がかかります

ディスク上にある文字起こしに対する、任意の第 2 パスです。整形 を参照してください。

estimate_cost

同じ source を受け取り、再生時間、推定 USD、上限、そしてジョブが許可されるかどうかを返します。Deepgram へのリクエストは行われません。URL の場合は、そうしなければ再生時間を知ることができないため、依然としてダウンロードが行われます。したがって、Deepgram の課金は発生しませんが、即座には完了しません。

CLI

transcribe ./interview.mp4 --diarize   # experimental, labels are often wrong
transcribe ./lecture.mp3 --estimate
transcribe ./clip.mp4 --json | jq .transcript_path

フラグ

デフォルト

意味

--diarize

オフ

実験的。 話者をラベル付け

--model <name>

DEEPGRAM_MODEL、それ以外は nova-3

Deepgram モデル

--language <code>

en

音声言語

--out <dir>

TRANSCRIPTION_OUTPUT_DIR、それ以外は ./output

出力ディレクトリ

--force

オフ

キャッシュヒット時も再文字起こし

--estimate

オフ

再生時間と推定 USD を表示して終了

--json

オフ

stdout に 1 つの JSON オブジェクトだけを表示

--help

すべてのフラグを一覧表示

終了コード: 0 成功、2 コスト上限超過による拒否、3 設定エラーまたはバイナリ不足、1 その他すべて。

transcribe format ./output/interview-final-8a2c1d0b7e64
transcribe format ./interview.mp4 --force

format サブコマンドは、ジョブフォルダ、またはそのジョブの元になったローカルファイルを受け取り、--force と --json を受け付けます。

整形

生の文字起こしは正確ですが、ほぼ読めたものではありません。一続きのテキストの壁になっているか、話者が聞こえない規則によって 4 文ごとに切り分けられたパラグラフになっています。整形パスは、言語モデルを単語そのものに触れさせることなく、これを修正します。

文字起こしは番号付きの文に分割され、安価な OpenRouter モデルに送信されます。モデルは構造のみを返します。パラグラフ区切りが後に続くインデックス、任意の { startIndex, title } セクション見出し、そして 3 つ以上 8 つ以下のケバブケースのトピックタグです。その後、保存された文の配列から Markdown が再構築されます。文の欠落、言い換え、捏造は、レビューによる保証ではなく構造上不可能です。モデルからテキストが一切返ってこないためです。

  • オプトイン。 transcribe が自動で整形することはありません。format_transcript または transcribe format を実行してください。

  • 部分的な失敗のみ。 文はウィンドウ単位で送信されます。プランが無効なウィンドウ、またはリクエストが失敗し続けるウィンドウは再試行され、その後、プレーンなパラグラフとして残され、スキップされた範囲として報告されます。文字起こしが生のレンダリングより悪い状態のまま残されることは決してありません。

  • 短い文字起こしにはセクションが付きません。 FORMAT_HEADINGS_MIN_SENTENCES 未満の場合、モデルにはパラグラフとタグのみが要求されます。4 分のボイスメモに、3 つのセクションを勝手に作り出す必要はありません。

  • 文字起こしと同じようにキャッシュされます。 プランはジョブフォルダ内の format.json に書き込まれます。2 回目の呼び出しはそこから再レンダリングし、コストはかかりません。force はモデルを再呼び出しします。整形済みジョブに対して transcribe を再実行すると、保存されたプランを上書きせずに再適用します。

  • 同じコストガード。 整形はリクエスト前に料金が見積もられ、MAX_COST_PER_JOB_USD を超えると拒否されます。この目的において、各呼び出しは独立したジョブです。Deepgram に既にかかったコストと合算されることは決してありません。

出力レイアウト

<TRANSCRIPTION_OUTPUT_DIR>/<slug>-<key12>/

  URL sources:   never-gonna-give-you-up-dQw4w9WgXcQ-1f3b9c2d4e5a/
  Local files:   interview-final-8a2c1d0b7e64/
  audio.opus       the 16 kHz mono upload
  audio.<ext>      the yt-dlp download, for URL sources, kept so re-runs never re-fetch
  response.json    Deepgram's raw response
  format.json      the structure plan, once the transcript has been formatted
  transcript.md    YAML front matter plus the rendered transcript

キャッシュ

キャッシュキーは、ソースの識別情報に加え、文字起こしを変えるオプションである model、diarize、language で構成されます。ローカルファイルはバイト列の SHA-256 で識別され、URL は yt-dlp の extractor id で識別されます。そのため、トラッキングパラメータや短縮リンクのバリエーションによって、有料の文字起こしが 2 回発生することはありません。

フォルダ名は見た目上のものです。URL の場合は動画タイトルに続けて動画 ID、ローカルファイルの場合はファイル名が使われます。ジョブの検索は末尾の <key12> だけで行われるため、読みやすい部分が何を表していてもフォルダは再利用されます。アップローダーが改名した動画や、このツールの旧バージョンが命名したフォルダでも、同じ文字起こしに 2 回費用を払う代わりにキャッシュにヒットします。

キャッシュヒット時は、古い Markdown を返すのではなく、保存された response.json から transcript.md を再レンダリングします。そのため、フォーマッタの改善が古いジョブにも無料で反映されます。Deepgram を再呼び出しするのは --force / force: true の場合だけです。

開発

npm test          # vitest
npm run typecheck
npm run build

どのテストもバイナリを起動せず、ネットワークにも触れません。ffprobe、ffmpeg、yt-dlp は注入可能なコマンドランナー経由で実行され、Deepgram は注入可能な fetch 経由で呼び出されます。

Related MCP Connectors

Related MCP Servers