Closed10

Deepgram の STT を試す

kun432kun432

公式サイト

https://deepgram.com/

ざっくりサービスとしては以下の4つの様子。

人間と機械の間で自然な会話ができる、統一された音声対音声 API です。1 つの強力な API を使用して、LLM を搭載した AI エージェントを作成できます。このエージェントは、人間と同じ知性と感情表現で、聞き、考え、話すことができます。

Deepgramの柔軟でリアルタイムな音声認識APIを活用し、音声優先アプリケーションを簡単に構築・拡張できます。開発者はオンプレミス、VPC、クラウドのいずれの環境でも迅速に開発し、より早くサービスを提供できます。

Aura-2は、Deepgramの次世代テキスト読み上げAPIです。リアルタイムのパフォーマンス、ドメイン固有の精度、クラウドおよびオンプレミス環境での安全でスケーラブルな導入により、自然でプロフェッショナルな音声を提供するように設計されています。

効率的なタスク特化型言語モデルを搭載しています。
会話音声から重要な洞察を大規模に抽出します。

今回はSTTを試す。

kun432kun432

STTで使えるモデルは以下に記載がある

https://developers.deepgram.com/docs/models-languages-overview

現時点では以下の2種類がメインライン。

  • nova-3
    • Deepgramの最高性能モデル。
    • ほぼすべてのユースケースに適用可能。
    • 特に、複数言語・バックグラウンドノイズ・クロストーク・遠距離音声等を含む音声の場合に推奨。
  • nova-2
    • 英語以外の文字起こし、およびフィラーワードの識別が必要なユースケースに推奨。

基本的には最新の nova-3 が推奨みたい。で、さらにドメイン特化なモデルごとに細かくモデルが用意されている様子。

モデル名 言語 用途
nova-3 / nova-3-general multi: マルチリンガル(日本語含む)
en / en-US: 英語
汎用
nova-3-medical en / en-US: 英語 医療分野向け?
nova-2 / nova-2-general multi: マルチリンガル(英語・スペイン語)
en / en-US: 英語
ja: 日本語
その他多数の言語に対応
汎用
nova-3-meeting en / en-US: 英語 会議向け?
nova-3-phonecall en / en-US: 英語 電話向け?
nova-3-finance en / en-US: 英語 金融分野向け?
nova-3-conversationalai en / en-US: 英語 会話向け?
nova-3-voicemail en / en-US: 英語 音声メール向け?
nova-3-video en / en-US: 英語 動画向け?
nova-3-drivethru en / en-US: 英語 ドライブするー向け?
nova-3-automotive en / en-US: 英語 自動車向け?
nova-3-atc en / en-US: 英語 航空管制向け?

まあ、たくさんバリエーションはあるけど、ほとんど英語のみで、日本語の場合は基本的に モデルnova-3+言語multi、または モデルnova-2+言語jaで使うと考えれば良さそう。

あとは一応Whisperも使えるみたい。

kun432kun432

料金

https://deepgram.com/pricing

プランは3つ

  • Pay As You Go
    • 完全従量課金
    • 登録時に$200分の無料クレジットが付与される
    • 同時接続数などレートリミットあり
  • Growth
    • 年払い $4000〜
    • Freeよりもレートリミットがゆるくなる
  • Enterprise
    • 年払い $15000〜
    • ホスティングやモデルのカスタマイズなどが可能になる

という感じみたいで、あとは個々のサービスの利用状況に応じてクレジットが消費される、という感じかな?クレジットは消費期限なしみたいで、有償プランでも余ったものは繰越しされるみたい。

STTは、

  • どのモデルを使うか?
  • バッチ or ストリーミングか?
  • どの料金プランを使うか?

で料金が異なる。 とりあえずPay As You Goの場合だとこんな感じか。

モデル バッチ ストリーミング
Nova-3(English) $0.0043/分 $0.0077/分
Nova-3(Multilingual) $0.0052/分 $0.0092/分
Nova-2 $0.0043/分 $0.0058/分

結構安い方じゃないかな?業界最安とまではいかないけども。

とりあえず$200のクレジットが使えるので、まずはPay As You Goでお試し。

kun432kun432

Getting Started (Pre-recorded)

https://developers.deepgram.com/docs/pre-recorded-audio

音声ファイルなどあらかじめ録音済みデータのバッチ文字起こし。

ローカルのMac上でPython SDKを使って試していく。

uvでプロジェクト作成

uv init -p 3.12.9 deepgram-stt-work && cd deepgram-stt-work

パッケージ追加

uv add deepgram-sdk python-dotenv
出力
 + deepgram-sdk==3.11.0

.envを作成して、APIキーをセット

.env
DEEPGRAM_API_KEY="XXXXXXXXX"

サンプル音声として、自分が開催した勉強会のYouTube動画から冒頭5分程度の音声を抜き出したオーディオファイルを用意した。

https://www.youtube.com/watch?v=Yl2kR6zLRY8

オーディオファイルが、ローカルとリモートのどちらにあるのか?でちょっとインタフェースが異なる。今回はローカルにあるファイルを対象にする。

prerecorded.py
import os
from dotenv import load_dotenv

from deepgram import (
    DeepgramClient,
    PrerecordedOptions,
    FileSource,
)

# オーディオファイルのパス
AUDIO_FILE = "voice_lunch_jp_5min.wav"

# 環境変数でAPIキーを読み込む
load_dotenv(verbose=True)

def main():
    try:
        # ステップ1: Deepgramクライアントの作成
        deepgram = DeepgramClient()

        with open(AUDIO_FILE, "rb") as file:
            buffer_data = file.read()

        payload: FileSource = {
            "buffer": buffer_data,
        }

        # ステップ2: オーディオ分析のオプションを設定
        options = PrerecordedOptions(
            model="nova-3",
            smart_format=True,
        )

        # ステップ3: テキストペイロードとオプションを使用してtranscribe_fileメソッドを呼び出す
        response = deepgram.listen.rest.v("1").transcribe_file(payload, options)

        # ステップ4: レスポンスを出力
        print(response.to_json(indent=4, ensure_ascii=False))

    except Exception as e:
        print(f"Exception: {e}")

if __name__ == "__main__":
    main()

実行

time uv run prerecorded.py

なのだが、レスポンスに何も入っていない・・・

出力
{
    "metadata": {
        "transaction_key": "deprecated",
        "request_id": "954583ba-d899-423a-8961-7deba88d7fdb",
        "sha256": "993962110222042ce3949ec50a5c844fc68986fe0da3fcfb9d58c5c6f769ccfb",
        "created": "2025-04-19T17:14:23.603Z",
        "duration": 268.75732,
        "channels": 1,
        "models": [
            "3b3aabe4-608a-46ac-9585-7960a25daf1a"
        ],
        "model_info": {
            "3b3aabe4-608a-46ac-9585-7960a25daf1a": {
                "name": "general-nova-3",
                "version": "2024-12-20.0",
                "arch": "nova-3"
            }
        }
    },
    "results": {
        "channels": [
            {
                "alternatives": [
                    {
                        "transcript": "",
                        "confidence": 0.0,
                        "words": [],
                        "paragraphs": {
                            "transcript": "\n",
                            "paragraphs": []
                        }
                    }
                ]
            }
        ]
    }
}

real	0m3.425s
user	0m0.224s
sys	0m0.069s

APIリファレンスを見てみると、どうも言語などは全てオプション値でデフォルトは指定されていない様子。ということで、言語を指定する。nova-3の場合は英語以外はmultiになる。

(snip)
        options = PrerecordedOptions(
            model="nova-3",
            smart_format=True,
            language="multi",
        )
(snip)

再度実行してみると上手く行った。

{
    "metadata": {
        "transaction_key": "deprecated",
        "request_id": "94262d3c-a2a8-412e-9b7e-0b7aeb936880",
        "sha256": "993962110222042ce3949ec50a5c844fc68986fe0da3fcfb9d58c5c6f769ccfb",
        "created": "2025-04-19T17:15:48.024Z",
        "duration": 268.75732,
        "channels": 1,
        "models": [
            "e8345677-a780-424f-bc88-44eda363a0ab"
        ],
        "model_info": {
            "e8345677-a780-424f-bc88-44eda363a0ab": {
                "name": "general-nova-3",
                "version": "2025-02-25.20117",
                "arch": "nova-3"
            }
        }
    },
    "results": {
        "channels": [
            {
                "alternatives": [
                    {
                        "transcript": "はい じゃあ 始め ます。 ちょっと まだ 来 られて ない 方も いらっしゃる んですけど ボ イス ラ ンチ、JP 始め ます。 皆さん 日 曜日。 はい 日 曜日 にお 集 いただき まして ありがとうございます。 今日 久し ぶりに ですね オフ ライン ということで 今日は ですね スペ シャル な ゲ をお 二人 来て いただいて おります ということで 今日 ちょっと ト ック に 回 ります けれども、VoiceRoad の シー ー である ウェ ン リ ーム さんと、 あと セ ール ス フォ ース の、 カ セ オ ール デザインのディ レ クター である ウェ イク ベ ネ ス さんに 来て いただいて ます。 ということで 日本 に来て いただいて ありがとうございました。 で 今日は ちょっと この 二 人に また 後で いろいろ と 聞 こう という コーナー がありますので、 そこで また 色々 と 聞 きたい と思います。 で 今日 のア ジェ ンダ なんですけども ちょっと 時間 過ぎ ちゃ いましたが まず 最初にVoiceLunchJP について ていう と あと 会 場 のところ ですね 少し ご 説明 させて いただいて 一つ 目の セ ッション で まず 私 の方から VoiceOverall 二 千 二 十 二 年の スキ ン 新 機能 とかですね その辺 の話を 少し させて いただいて その後 二 つ目 のセ ッション で ブ レイ ゼ ン さんと ブ ゼ さんに いろいろ カ ンバ セ ー ショ ナル デザイン について 何でも 聞 ぜ みたいな ところを 予定 しております。 で その後 十 五 時から 十 五 で 一旦 終了 という 形で させて いただいて ちょっと 一応VoiceOutch。JP タ しか 記念 撮影 は 必 ですよね。 なので それ だけ させて いただいて その後 ちょっと 一 時間 ぐらい 簡単 にお 菓子 と 飲み 物を 用意 してます ので懇 会 というのを そのまま させて いただ こう と思っています。VoiceLunchJP について なんですけども ボ イス ラ は ボ イスUI とか 音声 関連 ですね そういった 技術 に 実際に 携 わ っている 人 もしくは 興味 がある 人 そっち のため の グロ ーバ ル な コミュニ ティ という形 になって いて ボ イス ラ の日本 リ ージョン という 形 が ボ イス ラ になってます と。 過去 も ずっと やって ますけど オンライン オフ ライン で いろんな 音声 のデ ザイン だったり 技術 だったり というところで 情報 とかを 共有 して みんなで 業 盛り 上げて いこう ぜ というような ことで やって おります。 で 今日 のハ ッシュ タグ ですね、 ーク ボ イ スタ ンHJP で いろいろ と 自由 に 付き 合 してください。 で あと 会 ですね 今回 グラ ニ カ 様 のお 声 で 利用 させて いただいて ます。 ありがとうございます。 で ぜひ こちらも シェ を お願い したり ですと。 で 今日 と 配信 のところ も いろいろ と やって いただいて ます って 非常に 感謝 しております。 でちょっと 今 ごめんなさい、 今 コロナ で 会 場 に来 られる 方 とかも あまり いない ということで されて ない んですけれども、 通常 は なんか ここで アイ オ ーティー 機 器 の とか ガ ジェ ット とかを 展 されている ような ので、 そういった もの がある とき 今度 ですね また 体験 してみて いただければ な と思っています というところで、 あと す いません トイレ がこちら で あと タ 座 れる 方は こちら のところ になってます んで よろしくお願いします。 はい ということで 最初の挨拶 は これで、 じゃあ まず 私 の方 のセ ッション から 分けて いただきます というところで、 ボ イス ロー アップ デート 二 千 二 十 二 というところで、 今年 の新 機能 について 少し お話 をします。 自己 紹介 です。 清 水 と 申 します。 神 戸 で インフ のエ ンジ ニア をやって ますので 普段 はKubernetes とかErabest とかTeLaHome とか を い って まして 最近 ちょっと フリ ーラ ンス になります。 でちょっと 調べて みたらVoiceflow 一番 最初に 始めた のが 二 千 十 九 年の 頭 ぐらい なんで 大体 四 年 弱 ぐらい ですね いろいろ と 触 って まして あと 音声 関連 のコ ミュニ ティ のところ では、VoiceLunchJP、 今回 のやつ ですね 以外 にAJAG、AmazonAlexa、Japan ユ ーザー グループ とか、 あとVoiceFlow の日本 語 ユ ーザー グループ ということで、VFJUG というのを やって います。 日本語 コミュニ ティ の方はFacebook の方で やって ますので、 もし よ ろし ければ 見て いただければ なと思います。 あと 二 年 ぐらい 前に ですね、 技術 書 店 の方で ここに 今日 スタッフ で 聞いて いただいて いる 皆さん と ですね 一緒に 同時に 作る ということで 作った んですけれども、 もう これ ちょっと 二 年 ぐらい 経 って 中 身 が だいぶ 古 くなって しま っているので、既に ちょっと 販売 は 使用 しております。 今日は ちょっと 持って きた かった んですけど、 それ 忘れて しまいました。 はい、 なんで こういう ことも やって います",
                        "confidence": 0.95947266,
                        "words": [
                            {
                                "word": "はい",
                                "start": 1.52,
                                "end": 2.0,
                                "confidence": 0.97998047,
                                "punctuated_word": "はい",
                                "language": "ja"
                            },
                            {
                                "word": "じゃあ",
                                "start": 2.0,
                                "end": 2.3999999,
                                "confidence": 0.4267578,
                                "punctuated_word": "じゃあ",
                                "language": "ja"
                            },
                            {
                                "word": "始め",
                                "start": 2.3999999,
                                "end": 2.8799999,
                                "confidence": 0.97802734,
                                "punctuated_word": "始め",
                                "language": "ja"
                            },
                            {
                                "word": "ます。",
                                "start": 2.8799999,
                                "end": 3.12,
                                "confidence": 0.9313965,
                                "punctuated_word": "ます。",
                                "language": "ja"
                            },
(snip)
                            {
                                "word": "ことも",
                                "start": 267.93,
                                "end": 268.25,
                                "confidence": 0.9941406,
                                "punctuated_word": "ことも",
                                "language": "ja"
                            },
                            {
                                "word": "やって",
                                "start": 268.25,
                                "end": 268.57,
                                "confidence": 0.99121094,
                                "punctuated_word": "やって",
                                "language": "ja"
                            },
                            {
                                "word": "います",
                                "start": 268.57,
                                "end": 269.13,
                                "confidence": 0.7661133,
                                "punctuated_word": "います",
                                "language": "ja"
                            }
                        ],
                        "paragraphs": {
                            "transcript": "\nはい じゃあ 始め ます。 ちょっと まだ 来 られて ない 方も いらっしゃる んですけど ボ イス ラ ンチ、JP 始め ます。 皆さん 日 曜日。 はい 日 曜日 にお 集 いただき まして ありがとうございます。 今日 久し ぶりに ですね オフ ライン ということで 今日は ですね スペ シャル な ゲ をお 二人 来て いただいて おります ということで 今日 ちょっと ト ック に 回 ります けれども、VoiceRoad の シー ー である ウェ ン リ ーム さんと、 あと セ ール ス フォ ース の、 カ セ オ ール デザインのディ レ クター である ウェ イク ベ ネ ス さんに 来て いただいて ます。 ということで 日本 に来て いただいて ありがとうございました。 で 今日は ちょっと この 二 人に また 後で いろいろ と 聞 こう という コーナー がありますので、 そこで また 色々 と 聞 きたい と思います。 で 今日 のア ジェ ンダ なんですけども ちょっと 時間 過ぎ ちゃ いましたが まず 最初にVoiceLunchJP について ていう と あと 会 場 のところ ですね 少し ご 説明 させて いただいて 一つ 目の セ ッション で まず 私 の方から VoiceOverall 二 千 二 十 二 年の スキ ン 新 機能 とかですね その辺 の話を 少し させて いただいて その後 二 つ目 のセ ッション で ブ レイ ゼ ン さんと ブ ゼ さんに いろいろ カ ンバ セ ー ショ ナル デザイン について 何でも 聞 ぜ みたいな ところを 予定 しております。 で その後 十 五 時から 十 五 で 一旦 終了 という 形で させて いただいて ちょっと 一応VoiceOutch。JP タ しか 記念 撮影 は 必 ですよね。 なので それ だけ させて いただいて その後 ちょっと 一 時間 ぐらい 簡単 にお 菓子 と 飲み 物を 用意 してます ので懇 会 というのを そのまま させて いただ こう と思っています。VoiceLunchJP について なんですけども ボ イス ラ は ボ イスUI とか 音声 関連 ですね そういった 技術 に 実際に 携 わ っている 人 もしくは 興味 がある 人 そっち のため の グロ ーバ ル な コミュニ ティ という形 になって いて ボ イス ラ の日本 リ ージョン という 形 が ボ イス ラ になってます と。 過去 も ずっと やって ますけど オンライン オフ ライン で いろんな 音声 のデ ザイン だったり 技術 だったり というところで 情報 とかを 共有 して みんなで 業 盛り 上げて いこう ぜ というような ことで やって おります。 で 今日 のハ ッシュ タグ ですね、 ーク ボ イ スタ ンHJP で いろいろ と 自由 に 付き 合 してください。 で あと 会 ですね 今回 グラ ニ カ 様 のお 声 で 利用 させて いただいて ます。 ありがとうございます。 で ぜひ こちらも シェ を お願い したり ですと。 で 今日 と 配信 のところ も いろいろ と やって いただいて ます って 非常に 感謝 しております。 でちょっと 今 ごめんなさい、 今 コロナ で 会 場 に来 られる 方 とかも あまり いない ということで されて ない んですけれども、 通常 は なんか ここで アイ オ ーティー 機 器 の とか ガ ジェ ット とかを 展 されている ような ので、 そういった もの がある とき 今度 ですね また 体験 してみて いただければ な と思っています というところで、 あと す いません トイレ がこちら で あと タ 座 れる 方は こちら のところ になってます んで よろしくお願いします。 はい ということで 最初の挨拶 は これで、 じゃあ まず 私 の方 のセ ッション から 分けて いただきます というところで、 ボ イス ロー アップ デート 二 千 二 十 二 というところで、 今年 の新 機能 について 少し お話 をします。 自己 紹介 です。 清 水 と 申 します。 神 戸 で インフ のエ ンジ ニア をやって ますので 普段 はKubernetes とかErabest とかTeLaHome とか を い って まして 最近 ちょっと フリ ーラ ンス になります。 でちょっと 調べて みたらVoiceflow 一番 最初に 始めた のが 二 千 十 九 年の 頭 ぐらい なんで 大体 四 年 弱 ぐらい ですね いろいろ と 触 って まして あと 音声 関連 のコ ミュニ ティ のところ では、VoiceLunchJP、 今回 のやつ ですね 以外 にAJAG、AmazonAlexa、Japan ユ ーザー グループ とか、 あとVoiceFlow の日本 語 ユ ーザー グループ ということで、VFJUG というのを やって います。 日本語 コミュニ ティ の方はFacebook の方で やって ますので、 もし よ ろし ければ 見て いただければ なと思います。 あと 二 年 ぐらい 前に ですね、 技術 書 店 の方で ここに 今日 スタッフ で 聞いて いただいて いる 皆さん と ですね 一緒に 同時に 作る ということで 作った んですけれども、 もう これ ちょっと 二 年 ぐらい 経 って 中 身 が だいぶ 古 くなって しま っているので、既に ちょっと 販売 は 使用 しております。 今日は ちょっと 持って きた かった んですけど、 それ 忘れて しまいました。 はい、 なんで こういう ことも やって います",
                            "paragraphs": [
                                {
                                    "sentences": [
                                        {
                                            "text": "はい じゃあ 始め ます。 ちょっと まだ 来 られて ない 方も いらっしゃる んですけど ボ イス ラ ンチ、JP 始め ます。 皆さん 日 曜日。 はい 日 曜日 にお 集 いただき まして ありがとうございます。 今日 久し ぶりに ですね オフ ライン ということで 今日は ですね スペ シャル な ゲ をお 二人 来て いただいて おります ということで 今日 ちょっと ト ック に 回 ります けれども、VoiceRoad の シー ー である ウェ ン リ ーム さんと、 あと セ ール ス フォ ース の、 カ セ オ ール デザインのディ レ クター である ウェ イク ベ ネ ス さんに 来て いただいて ます。 ということで 日本 に来て いただいて ありがとうございました。 で 今日は ちょっと この 二 人に また 後で いろいろ と 聞 こう という コーナー がありますので、 そこで また 色々 と 聞 きたい と思います。 で 今日 のア ジェ ンダ なんですけども ちょっと 時間 過ぎ ちゃ いましたが まず 最初にVoiceLunchJP について ていう と あと 会 場 のところ ですね 少し ご 説明 させて いただいて 一つ 目の セ ッション で まず 私 の方から VoiceOverall 二 千 二 十 二 年の スキ ン 新 機能 とかですね その辺 の話を 少し させて いただいて その後 二 つ目 のセ ッション で ブ レイ ゼ ン さんと ブ ゼ さんに いろいろ カ ンバ セ ー ショ ナル デザイン について 何でも 聞 ぜ みたいな ところを 予定 しております。 で その後 十 五 時から 十 五 で 一旦 終了 という 形で させて いただいて ちょっと 一応VoiceOutch。JP タ しか 記念 撮影 は 必 ですよね。 なので それ だけ させて いただいて その後 ちょっと 一 時間 ぐらい 簡単 にお 菓子 と 飲み 物を 用意 してます ので懇 会 というのを そのまま させて いただ こう と思っています。VoiceLunchJP について なんですけども ボ イス ラ は ボ イスUI とか 音声 関連 ですね そういった 技術 に 実際に 携 わ っている 人 もしくは 興味 がある 人 そっち のため の グロ ーバ ル な コミュニ ティ という形 になって いて ボ イス ラ の日本 リ ージョン という 形 が ボ イス ラ になってます と。 過去 も ずっと やって ますけど オンライン オフ ライン で いろんな 音声 のデ ザイン だったり 技術 だったり というところで 情報 とかを 共有 して みんなで 業 盛り 上げて いこう ぜ というような ことで やって おります。 で 今日 のハ ッシュ タグ ですね、 ーク ボ イ スタ ンHJP で いろいろ と 自由 に 付き 合 してください。 で あと 会 ですね 今回 グラ ニ カ 様 のお 声 で 利用 させて いただいて ます。 ありがとうございます。 で ぜひ こちらも シェ を お願い したり ですと。 で 今日 と 配信 のところ も いろいろ と やって いただいて ます って 非常に 感謝 しております。 でちょっと 今 ごめんなさい、 今 コロナ で 会 場 に来 られる 方 とかも あまり いない ということで されて ない んですけれども、 通常 は なんか ここで アイ オ ーティー 機 器 の とか ガ ジェ ット とかを 展 されている ような ので、 そういった もの がある とき 今度 ですね また 体験 してみて いただければ な と思っています というところで、 あと す いません トイレ がこちら で あと タ 座 れる 方は こちら のところ になってます んで よろしくお願いします。 はい ということで 最初の挨拶 は これで、 じゃあ まず 私 の方 のセ ッション から 分けて いただきます というところで、 ボ イス ロー アップ デート 二 千 二 十 二 というところで、 今年 の新 機能 について 少し お話 をします。 自己 紹介 です。 清 水 と 申 します。 神 戸 で インフ のエ ンジ ニア をやって ますので 普段 はKubernetes とかErabest とかTeLaHome とか を い って まして 最近 ちょっと フリ ーラ ンス になります。 でちょっと 調べて みたらVoiceflow 一番 最初に 始めた のが 二 千 十 九 年の 頭 ぐらい なんで 大体 四 年 弱 ぐらい ですね いろいろ と 触 って まして あと 音声 関連 のコ ミュニ ティ のところ では、VoiceLunchJP、 今回 のやつ ですね 以外 にAJAG、AmazonAlexa、Japan ユ ーザー グループ とか、 あとVoiceFlow の日本 語 ユ ーザー グループ ということで、VFJUG というのを やって います。 日本語 コミュニ ティ の方はFacebook の方で やって ますので、 もし よ ろし ければ 見て いただければ なと思います。 あと 二 年 ぐらい 前に ですね、 技術 書 店 の方で ここに 今日 スタッフ で 聞いて いただいて いる 皆さん と ですね 一緒に 同時に 作る ということで 作った んですけれども、 もう これ ちょっと 二 年 ぐらい 経 って 中 身 が だいぶ 古 くなって しま っているので、既に ちょっと 販売 は 使用 しております。 今日は ちょっと 持って きた かった んですけど、 それ 忘れて しまいました。 はい、 なんで こういう ことも やって います",
                                            "start": 1.52,
                                            "end": 269.13
                                        }
                                    ],
                                    "start": 1.52,
                                    "end": 269.13,
                                    "num_words": 646
                                }
                            ]
                        },
                        "languages": [
                            "ja"
                        ]
                    }
                ]
            }
        ]
    }
}

real	0m3.855s
user	0m0.279s
sys	0m0.065s

文字起こし結果を取得するならば、results.channels[0].alternatives[0].transcriptで取れそう。で、smart_format=Trueを付与すると、句読点の付与や(英語の場合)先頭文字の大文字化などが行われたうえで、単語単位のタイムスタンプも付与されるみたい。日本語の場合はどうやらある程度トークン的な単位で分割されているように思える。

肝心の文字起こしの精度は、うーん・・・ちょっと抜けが多い感じかなぁ・・・

はい じゃあ 始め ます。 ちょっと まだ 来 られて ない 方も いらっしゃる んですけど ボ イス ラ ンチ、JP 始め ます。 皆さん 日 曜日。 はい 日 曜日 にお 集 いただき まして ありがとうございます。 今日 久し ぶりに ですね オフ ライン ということで 今日は ですね スペ シャル な ゲ をお 二人 来て いただいて おります ということで 今日 ちょっと ト ック に 回 ります けれども、VoiceRoad の シー ー である ウェ ン リ ーム さんと、 あと セ ール ス フォ ース の、 カ セ オ ール デザインのディ レ クター である ウェ イク ベ ネ ス さんに 来て いただいて ます。 ということで 日本 に来て いただいて ありがとうございました。 で 今日は ちょっと この 二 人に また 後で いろいろ と 聞 こう という コーナー がありますので、 そこで また 色々 と 聞 きたい と思います。 で 今日 のア ジェ ンダ なんですけども ちょっと 時間 過ぎ ちゃ いましたが まず 最初にVoiceLunchJP について ていう と あと 会 場 のところ ですね 少し ご 説明 させて いただいて 一つ 目の セ ッション で まず 私 の方から VoiceOverall 二 千 二 十 二 年の スキ ン 新 機能 とかですね その辺 の話を 少し させて いただいて その後 二 つ目 のセ ッション で ブ レイ ゼ ン さんと ブ ゼ さんに いろいろ カ ンバ セ ー ショ ナル デザイン について 何でも 聞 ぜ みたいな ところを 予定 しております。 で その後 十 五 時から 十 五 で 一旦 終了 という 形で させて いただいて ちょっと 一応VoiceOutch。JP タ しか 記念 撮影 は 必 ですよね。 なので それ だけ させて いただいて その後 ちょっと 一 時間 ぐらい 簡単 にお 菓子 と 飲み 物を 用意 してます ので懇 会 というのを そのまま させて いただ こう と思っています。VoiceLunchJP について なんですけども ボ イス ラ は ボ イスUI とか 音声 関連 ですね そういった 技術 に 実際に 携 わ っている 人 もしくは 興味 がある 人 そっち のため の グロ ーバ ル な コミュニ ティ という形 になって いて ボ イス ラ の日本 リ ージョン という 形 が ボ イス ラ になってます と。 過去 も ずっと やって ますけど オンライン オフ ライン で いろんな 音声 のデ ザイン だったり 技術 だったり というところで 情報 とかを 共有 して みんなで 業 盛り 上げて いこう ぜ というような ことで やって おります。 で 今日 のハ ッシュ タグ ですね、 ーク ボ イ スタ ンHJP で いろいろ と 自由 に 付き 合 してください。 で あと 会 ですね 今回 グラ ニ カ 様 のお 声 で 利用 させて いただいて ます。 ありがとうございます。 で ぜひ こちらも シェ を お願い したり ですと。 で 今日 と 配信 のところ も いろいろ と やって いただいて ます って 非常に 感謝 しております。 でちょっと 今 ごめんなさい、 今 コロナ で 会 場 に来 られる 方 とかも あまり いない ということで されて ない んですけれども、 通常 は なんか ここで アイ オ ーティー 機 器 の とか ガ ジェ ット とかを 展 されている ような ので、 そういった もの がある とき 今度 ですね また 体験 してみて いただければ な と思っています というところで、 あと す いません トイレ がこちら で あと タ 座 れる 方は こちら のところ になってます んで よろしくお願いします。 はい ということで 最初の挨拶 は これで、 じゃあ まず 私 の方 のセ ッション から 分けて いただきます というところで、 ボ イス ロー アップ デート 二 千 二 十 二 というところで、 今年 の新 機能 について 少し お話 をします。 自己 紹介 です。 清 水 と 申 します。 神 戸 で インフ のエ ンジ ニア をやって ますので 普段 はKubernetes とかErabest とかTeLaHome とか を い って まして 最近 ちょっと フリ ーラ ンス になります。 でちょっと 調べて みたらVoiceflow 一番 最初に 始めた のが 二 千 十 九 年の 頭 ぐらい なんで 大体 四 年 弱 ぐらい ですね いろいろ と 触 って まして あと 音声 関連 のコ ミュニ ティ のところ では、VoiceLunchJP、 今回 のやつ ですね 以外 にAJAG、AmazonAlexa、Japan ユ ーザー グループ とか、 あとVoiceFlow の日本 語 ユ ーザー グループ ということで、VFJUG というのを やって います。 日本語 コミュニ ティ の方はFacebook の方で やって ますので、 もし よ ろし ければ 見て いただければ なと思います。 あと 二 年 ぐらい 前に ですね、 技術 書 店 の方で ここに 今日 スタッフ で 聞いて いただいて いる 皆さん と ですね 一緒に 同時に 作る ということで 作った んですけれども、 もう これ ちょっと 二 年 ぐらい 経 って 中 身 が だいぶ 古 くなって しま っているので、既に ちょっと 販売 は 使用 しております。 今日は ちょっと 持って きた かった んですけど、 それ 忘れて しまいました。 はい、 なんで こういう ことも やって います

Artificial Analysisの比較表を見ていると、そこそこ速い・そこそこ安い・精度はトップレベルからはやや落ちる、という感じに見える。

https://artificialanalysis.ai/speech-to-text

kun432kun432

Getting Started (Streaming)

https://developers.deepgram.com/docs/live-streaming-audio

次はストリーミング。実は個人的に期待しているのはこちらだったりする。

マイクからの音声をリアルタイムに文字起こしするサンプルは以下にある。

同期
https://github.com/deepgram/deepgram-python-sdk/tree/main/examples/speech-to-text/websocket/microphone

非同期
https://github.com/deepgram/deepgram-python-sdk/tree/main/examples/speech-to-text/websocket/async_microphone

同期のサンプルコードを試してみる。まず依存ライブラリをインストール。

uv add pyaudio playsound3 sounddevice numpy
出力
 + numpy==2.2.4
 + playsound3==3.2.3
 + pyaudio==0.2.14
 + sounddevice==0.5.1

サンプルコード。ちょっとコメントなどがあってない箇所があるように思えるが、とりあえずざっと日本語化してloggingで出力するようにした。

from dotenv import load_dotenv
from time import sleep
import logging

from deepgram.utils import verboselogs

from deepgram import (
    DeepgramClient,
    DeepgramClientOptions,
    LiveTranscriptionEvents,
    LiveOptions,
    Microphone,
)

load_dotenv()

# 発話終了時に使用する is_final=true のメッセージを収集する
is_finals = []


def main():
    
    logging.basicConfig(
        level=logging.INFO,
        format='%(asctime)s %(levelname)s:%(message)s',
        handlers=[logging.StreamHandler()]
    )

    try:
        # クライアントの設定例。ログの値: WARNING, VERBOSE, DEBUG, SPAM
        # ```
        # config = DeepgramClientOptions(
        #     verbose=verboselogs.DEBUG, options={"keepalive": "true"}
        # )
        # deepgram: DeepgramClient = DeepgramClient("", config)
        # ```
        # 指定がない場合はデフォルトの設定を使用
        deepgram: DeepgramClient = DeepgramClient()

        dg_connection = deepgram.listen.websocket.v("1")

        def on_open(self, open, **kwargs):
            logging.info("接続開始")

        def on_message(self, result, **kwargs):
            global is_finals
            sentence = result.channel.alternatives[0].transcript
            if len(sentence) == 0:
                return
            if result.is_final:
                # 出力量が多いため、コメントアウトしている
                #logging.info(f"メッセージ: {result.to_json(indent=4, ensure_ascii=False)}")
                # これらを収集して、speech_final=true が得られたときに連結する必要がある。
                # ドキュメントを参照: https://developers.deepgram.com/docs/understand-endpointing-interim-results
                is_finals.append(sentence)

                # Speech Final は、発話終了を判断するための十分な無音を検出したことを意味する
                # Speech final は、エンドポイント値がトリガーされるとすぐにトリガーされるため、最も低いレイテンシの結果となる
                if result.speech_final:
                    utterance = " ".join(is_finals)
                    logging.info(f"最終認識結果: {utterance}")
                    is_finals = []
                else:
                    # これらは、発話内容をリアルタイム文字起こしする場合に役に立つ
                    logging.info(f"最終認識結果か?: {sentence}")
            else:
                # これらは、リアルタイム文字起こしで、中間結果を更新する場合に役に立つ
                logging.info(f"中間認識結果: {sentence}")

        def on_metadata(self, metadata, **kwargs):
            logging.info(f"メタデータ: {metadata}")

        def on_speech_started(self, speech_started, **kwargs):
            logging.info("発話開始")

        def on_utterance_end(self, utterance_end, **kwargs):
            logging.info("発話終了")
            global is_finals
            if len(is_finals) > 0:
                utterance = " ".join(is_finals)
                logging.info(f"発話終了: {utterance}")
                is_finals = []

        def on_close(self, close, **kwargs):
            logging.info("接続終了")

        def on_error(self, error, **kwargs):
            logging.error(f"エラー処理: {error}")

        def on_unhandled(self, unhandled, **kwargs):
            logging.error(f"未処理のWebSocketメッセージ: {unhandled}")

        dg_connection.on(LiveTranscriptionEvents.Open, on_open)
        dg_connection.on(LiveTranscriptionEvents.Transcript, on_message)
        dg_connection.on(LiveTranscriptionEvents.Metadata, on_metadata)
        dg_connection.on(LiveTranscriptionEvents.SpeechStarted, on_speech_started)
        dg_connection.on(LiveTranscriptionEvents.UtteranceEnd, on_utterance_end)
        dg_connection.on(LiveTranscriptionEvents.Close, on_close)
        dg_connection.on(LiveTranscriptionEvents.Error, on_error)
        dg_connection.on(LiveTranscriptionEvents.Unhandled, on_unhandled)

        options: LiveOptions = LiveOptions(
            model="nova-3",
            language="multi",
            # 出力に smart format を適用
            smart_format=True,
            # rawオーディオフォーマットの詳細
            encoding="linear16",
            channels=1,
            sample_rate=16000,
            # "UtteranceEnd" を取得するには、次の設定が必要
            interim_results=True,
            utterance_end_ms="1000",
            vad_events=True,
            # 発話終了を待つための無音の時間(ミリ秒)
            endpointing=300,
        )

        addons = {
            # 追加の数値を待つのを防ぐ
            "no_delay": "true"
        }

        logging.info("\n\nEnterキーを押して録音を停止...\n\n")
        if dg_connection.start(options, addons=addons) is False:
            logging.error("Deepgramへの接続に失敗しました")
            return

        # デフォルトの入力デバイスでマイクストリームを開く
        microphone = Microphone(dg_connection.send)

        # マイクストリームを開始
        microphone.start()

        # 終了するまで待つ
        input("")

        # マイクストリームを閉じる
        microphone.finish()

        # 終了を示す
        dg_connection.finish()

        logging.info("終了")
        # sleep(30)  # 30秒待って、追加のソケットアクティビティがあるかどうかを確認
        # print("Really done!")

    except Exception as e:
        logging.error(f"ソケットを開けませんでした: {e}")
        return


if __name__ == "__main__":
    main()

実行。

uv run streaming_from_mic.py

新幹線のアナウンスを発話してみた。

https://denden-lab.com/tokaido-shinkansen-nozomi-announce/

結果。

出力
Attempting to set API key from environment variable
2025-04-20 03:27:45,227 INFO:Attempting to set API key from environment variable
2025-04-20 03:27:45,227 INFO:

Enterキーを押して録音を停止...


2025-04-20 03:27:45,886 INFO:接続開始
2025-04-20 03:27:48,076 INFO:発話開始
2025-04-20 03:27:49,122 INFO:中間認識結果: Chiamo, sin
2025-04-20 03:27:50,143 INFO:中間認識結果: 今日も 新 幹 線を ご 利用
2025-04-20 03:27:51,658 INFO:発話開始
2025-04-20 03:27:51,741 INFO:最終認識結果か?: 今日も 新 幹 線を ご 利用 ください まして
2025-04-20 03:27:52,201 INFO:中間認識結果: ありがとう
2025-04-20 03:27:53,282 INFO:最終認識結果: 今日も 新 幹 線を ご 利用 ください まして ありがとうございます。
2025-04-20 03:27:54,221 INFO:発話開始
2025-04-20 03:27:54,247 INFO:中間認識結果: この
2025-04-20 03:27:54,248 INFO:発話終了
2025-04-20 03:27:55,241 INFO:発話開始
2025-04-20 03:27:55,259 INFO:最終認識結果: この 電車 は
2025-04-20 03:27:56,286 INFO:中間認識結果: 号 と
2025-04-20 03:27:57,310 INFO:中間認識結果: 望 み 号 東京 駅
2025-04-20 03:27:57,828 INFO:最終認識結果: 望 み 号 東京 駅 です。
2025-04-20 03:27:58,827 INFO:発話開始
2025-04-20 03:27:58,845 INFO:中間認識結果: 途中
2025-04-20 03:28:00,362 INFO:発話開始
2025-04-20 03:28:00,384 INFO:最終認識結果: 途中の停 車 駅 は
2025-04-20 03:28:01,387 INFO:発話開始
2025-04-20 03:28:01,416 INFO:発話終了
2025-04-20 03:28:02,453 INFO:中間認識結果: 名 古 屋、 市
2025-04-20 03:28:03,473 INFO:中間認識結果: 名 古 屋 新 横 浜
2025-04-20 03:28:04,491 INFO:中間認識結果: 名 古 屋 新 横 浜 品 川
2025-04-20 03:28:05,569 INFO:最終認識結果: 名 古 屋 新 横 浜 品 川 です。
2025-04-20 03:28:05,995 INFO:発話開始
2025-04-20 03:28:06,542 INFO:中間認識結果: 電車 は
2025-04-20 03:28:07,558 INFO:中間認識結果: この 電車 は 遺 伝 跡 禁煙
2025-04-20 03:28:09,158 INFO:最終認識結果: この 電車 は 遺 伝 跡 禁煙 となって おり
2025-04-20 03:28:09,581 INFO:発話開始
2025-04-20 03:28:10,129 INFO:中間認識結果: こ を 吸 わ
2025-04-20 03:28:11,151 INFO:中間認識結果: お た ば こ を 吸 われる お客 様は
2025-04-20 03:28:12,197 INFO:中間認識結果: お た ば こ を 吸 われる お客 様は喫煙 ルーム を
2025-04-20 03:28:13,202 INFO:中間認識結果: お た ば こ を 吸 われる お客 様は喫煙 ルーム をご 利用 ください。
2025-04-20 03:28:13,736 INFO:最終認識結果: お た ば こ を 吸 われる お客 様は喫煙 ルーム をご 利用 ください。
2025-04-20 03:28:14,189 INFO:発話開始
2025-04-20 03:28:14,720 INFO:発話終了
2025-04-20 03:28:16,236 INFO:発話開始
2025-04-20 03:28:16,746 INFO:発話開始

2025-04-20 03:28:17,233 INFO:接続終了
2025-04-20 03:28:17,401 INFO:メタデータ: {
    "type": "Metadata",
    "transaction_key": "deprecated",
    "request_id": "38eb6951-d2f9-4797-add4-34f5c5ec7777",
    "sha256": "8afcb7fb89ff2dd70766ab124aa022bdd4102f1bbc90bd245522334fadec4b53",
    "created": "2025-04-19T18:27:45.799Z",
    "duration": 30.215376,
    "channels": 1,
    "models": [
        "8fc0d9e9-3a3c-4ed2-abb0-3704abc815d0"
    ],
    "model_info": {
        "8fc0d9e9-3a3c-4ed2-abb0-3704abc815d0": {
            "name": "general-nova-3",
            "version": "2025-02-22.5738",
            "arch": "nova-3"
        }
    }
}
2025-04-20 03:28:18,913 INFO:終了

Google等と同様に音声認識結果は中間認識結果("is_final": False)と最終認識結果("is_final": True)として返ってくるのだけど、Speech Finalってのもあって、ほんとに発話の最後かどうか?というところも確認できるみたい。

ざっとログを見てて、中間認識結果と最終認識結果の間隔は比較的短めなのかもしれないなと感じた。Google TTSなどだと、最後の中間認識結果から最終認識結果までの間にそれなりのレイテンシーがある(かつ、ばらつきもあって速いときと遅い時がある)印象で、それに比べると比較的速いかも?という気がした。ただ、バッチの時と同様、あまり精度は良くないかなーという感はある。

kun432kun432

まとめ

音声系のフレームワークを色々いじってると、結構STTのデフォルトで使用されていることが多くて、なんでだろうなーとか思ってたけど、多分中間〜最終認識結果までのレイテンシーが低いのだろうと自分は思った。

日本語も対応はしているものの、自分が試した限りはちょっと精度的にはイマイチかなぁ?というところ。モデルの説明を見ていると、Nova-3には英語専用のモデルがあるし、Nova-2にも多数のドメインに対応したモデルが英語専用で存在する。おそらく英語だと学習量が豊富なのではないか、と推測。

このあたりも含めて、英語圏では一定の基準を満たしているのではないだろうか?というところ。

kun432kun432

なお、TTSは日本語には対応していない模様・・・

kun432kun432

Google STTからのマイグレーションガイドがある

https://developers.deepgram.com/docs/migrating-from-google-speech-to-text-stt-to-deepgram#differences

これによると、ストリーミングのラグがGoogleよりも小さいとある。

同様にAmazon Transcribeも同じ。

https://developers.deepgram.com/docs/migrating-from-amazon-web-services-aws-transcribe-to-deepgram#differences

なるほど、体感的に速く感じたのは、公式で謳われている通りなのね。惜しいな、日本語の精度がもっと高ければ・・・

kun432kun432

RedditでDeepgramのVoice Agent良かったという話。

https://www.reddit.com/r/speechtech/comments/1lp7ey4/deepgram_voice_agent/

スレ主はVapiとかRetell AIみたいな音声エージェントプラットフォームがイマイチだったのに対してDeepgramの良さを書いてるけども、自分が上でASRを試した感じからすると、日本語の場合は精度的にどんなもんかなぁというところ。

このスクラップは5ヶ月前にクローズされました