natural-voice は何をしますか?
ほとんどの「ロボット的な」ElevenLabs音声は、音声の問題ではありません。スクリプトの問題です。 モデルは与えられたものをそのまま読み上げます。「目で読むため」に書かれたスクリプト(見出し、終止符で区切られた断片、数字、ダッシュ)は、どの声で読み上げてもスタッカートのように聞こえます。
このフォルダにある3つのツールは実際に動作します。テキストだけで判断せず、実際に使ってみてください。
python3 speakable.py script.txt # これは耳で聴くために書かれているか?
python3 takes.py script.txt --voice VOICE_ID # シード指定テイク(有料。事前に確認あり)
python3 gaps.py takes/ # 文途中のギャップでテイクをランク付け
3つともプレーンなPython 3.9+で、追加パッケージは不要です。gaps.pyは、PATHにffmpegがあればそれを使って音声ファイルから直接ギャップを確認します。
ワークフロー
1. 何も変更する前に診断する。 すでにテイクがあるなら、gaps.pyを実行します。文の内部(コンマや終止符の後ではない場所)で0.2秒以上のギャップがあると、人々はそれを「AIっぽい」と感じます。私たち自身のビフォアテイクでは、フックの途中で「run」の前と「Instagram」の前に0.3秒の停止がありました。編集によるものではありません。ギャップは生のファイルにありました。
2. 耳で聴くために書き換える。 speakable.pyを実行し、すべてのフラグを修正します。ルールは以下の通りです:
- 文であって、見出しではない。 「13 free Claude skills now run your Instagram.」はタイトルです。「Thirteen free Claude skills run your whole Instagram.」は人が言うことです。
- リストはコンマで区切り、終止符は使わない。 「Reels. Captions. Carousels.」とするとモデルが3回停止します。「reels, captions, carousels, stories」のほうが流れます。
- 話す行では数字を単語で書く。 「eighty-four out of a hundred」であって「84 out of 100」ではありません。画面上のテキストは数字のままで構いません。
- 短縮形を使う(you've, it's, we'll)。「you have」と声に出して言う人はいません。
- 断片を「so」「and」「then」でつなぐ。 接続詞はモデルに続けるよう促す合図です。
- ダッシュは使わない。 ElevenLabsはダッシュを短い休止として扱い、自身でも「一貫性に欠ける」と述べています。続けるにはコンマを、間を取るには省略記号を使います。
- SSMLは使わない。
<break time="1s"/>はEleven v4またはv3ではサポートされていません。
3. 演出を加える。 Eleven v4は角括弧で囲まれたオーディオタグを受け付けます。ビートの先頭に1つだけタグを置き、すべての行に付ける必要はありません。タグはその行の内容に合ったものを選びます。タグの一覧はtags.mdを参照してください。speakable.pyは未知のタグをフラグします。未知のタグは効果音として読み上げられる可能性があります。
[excited] Thirteen free Claude skills run your whole Instagram.
[mischievously] So we let it write this Reel...
句読点も演出の一部です。省略記号は重みのある休止、感嘆符はエネルギー、大文字は強調を追加します(重要な単語に一度だけ使います)。
4. 設定。 eleven_v4の場合:
| 設定 | 値 | 理由 |
|---|---|---|
| stability | 0.30 ~ 0.40 | 低いほど「より広い感情表現」が可能。デフォルトの0.5はより平坦。0.3未満だとテイクが不安定になる可能性があります。 |
| similarity_boost | 0.75 | デフォルト。声そのものを維持します。 |
| style | 0 | デフォルト。これ以外の値はレイテンシーを増加させます。 |
| speed | 1.0 ~ 1.08 | 許容範囲は0.7~1.2。SNSのナレーションでは1.0を少し超えたあたりが適切です。 |
5. 同じテキストで3つのテイクを、異なるシードで生成する。 1テイクだけでは運任せです。takes.pyをシード1、2、3で実行し、次にgaps.pyでランク付けします。上位2つを聴いて、耳で選びます。シードは保持しておいてください。再実行時に同じテイクに近いものが得られます(ElevenLabsは「ベストエフォート」としていますが、保証はされません)。
6. 穏やかに編集する。 編集ソフトで無音をカットする場合、文の後には約1秒、コンマの後にはほとんどの場合約1秒を残してください。毎回同じ長さに無音をカットすると、それも機械的に聞こえる原因になります。
7. それでも生成されたように聞こえるか? つまみをいじるのをやめましょう。スマートフォンでその行を自分で録音し、ElevenLabsのVoice Changer(音声変換)を使って目的の声に変換してください。あなたのタイミング、強調、感情がそのまま引き継がれ、声だけが変わります。
測定結果
私たち自身のリールの1つ(ファイルはexamples/にあります)を使用した場合:
| ビフォア | アフター | |
|---|---|---|
| スクリプト | 目で読むため:断片、数字 | 耳で聴くため:speakable.pyクリーン |
| タグ | なし | [excited], [mischievously] |
| 設定 | stability 0.5, speed 1.0 | stability 0.35, speed 1.05 |
| テイク数 | 1 | 3シード、gaps.pyで選定後、耳で選定 |
speakable.pyスコア | 65, REWRITE(終止符区切りのリスト、数字、タグなし) | 100, SPEAKABLE |
| 文内部のギャップ | フック内の「now」と「run」の間で0.34秒 | なし |
声も変更しました(WillからChrisへ)。そのため、これは単一設定の実験室テストではありません。スクリプトの書き換えが、聞こえる最大の違いをもたらしました。
ルール
- 有料リクエストを送信する前に、必ずコストを伝えること。
takes.pyは文字数を表示し、--yesを渡さない限り停止します。 - APIキーを表示したりコミットしたりしないこと。
takes.pyは環境変数ELEVENLABS_API_KEYのみを読み取ります。 - ラベルを付けること。 音声が生成されたものである場合、そのプラットフォームのAIラベルを有効にしてください。