AI読み上げサービス にじボイス API使ってみた ~AIで感情豊かな読み上げ実況を作成できる!?~
こんにちはRcatです。
今回はスマホに面白そうな通知が入って来ましたので試すことにしました。
その名もにじボイス。
簡単に言うとAIを使った音声合成サービス。
最近VOICEVOXを使ったツールを作るのにはまっていますが、そんな私の好奇心をくすぐるサービスです。
ボイスボックスを使った全自動吹き替えツールを最近紹介していますが、代わりにこのサービスを使うこともできそうですね。
にじボイスを使って吹き替えた動画はこちら
フリーソフトのVOICEVOXはこちら
はじめに
利用規約
情報や作品の活用時は事前に利用規約をご確認ください。
https://note.com/rcat999/n/nb6a601a36ef5
コメントについて
利用規約のガイドラインを確認の上コメントしてください
にじボイスとは
公式を説明によると、AIを活用した音声生成プラットフォームです。
たくさんのキャラクターが用意されており、好きなキャラに対してテキストを読ませることができます。
なんと現段階で100キャラクターいます。
早速APIを使ってみる
というわけで、いきなりAPIを使います。
もうお分かりだと思いますが、APIがないサービスに私が手を出すことはありません。逆に言えば私はAPIがあれば食いつきますw。
そして今後の為にPythonのクラス化をします。
APIって何?
APIはこういった外部のサービスを自分のプログラムの中で使用するためのインターフェースです。
このサービスでは特定のURLに特定のボディを送りつけることで音声生成ができるみたいです。
APIにログインする
現段階では公式サイト右上ににじボイスAPIというリンクがあるので、そこからAPIへログインします。
なお、APIは有料サービスです。
このサービスでは文字数で課金されます。課金というか、事前に購入しておく感じですね。できるだけ漢字で入力した方が節約できる??
ただし、初回はお試し用に5000文字が付与されています。今回はこれを使って試していきます。
APIキーを確認する
左のメニューから自分のAPIキーを確認しましょう。
これがばれると他の人に使われてしまうので、絶対に公開しないようにしてください。
APIを実行する
左のメニューのドキュメントから使い方を確認できます。
なお、利用規約により音声を使用する際はクレジットの表記が必要なようです。無料分だけではなく、課金した場合でもクレジットがいるんですね。気を付けましょう。
キャラクターの一覧を確認する
まず、最初にキャラクターと対応するIDの一覧を取得します。
左のメニューのボイス一覧からでもブラウザ上で確認できますが、自分のプログラムに組み込む場合はAPIで取得できた方がいいでしょう
以下が私のターミナルでの実行結果です。
一部ぼかした方がいいと思われる内容はぼかしています。
>>>import requests,pprint
>>>url = "https://api.nijivoice.com/api/platform/v1/voice-actors"
>>>header = {
... "accept": "application/json",
... "x-api-key":"ここに自分のAPIキーを入れる"
...}
>>>resp = requests.get(url,headers=header)
>>>characters = resp.json()
>>> characters.keys()
dict_keys(['voiceActors'])
>>> len(characters["voiceActors"])
100
>>>pprint.pprint(characters["voiceActors"][0])
{'age': 15,
'birthDay': 3,
'birthMonth': 3,
'gender': 'FEMALE',
'id': 'キャラのUUID',
'largeImageUrl': '画像のURL2',
'mediumImageUrl': '画像のURL',
'name': '日本語の名前',
'nameReading': '読み仮名',
'recommendedVoiceSpeed': 0.8,
'sampleScript': 'サンプル音声の読み',
'sampleVoiceUrl': 'サンプル音声のURL',
'smallImageUrl': 'アイコンのURL',
'voiceStyles': [{'id': 58, 'style': '素直'}, {'id': 41, 'style': ' 明るい'}]}
情報はJSON形式でありPythonでは辞書に変換可能です。
また、一番最初のキーが"voiceActors"でこの中に全てのキャラクターがリストで格納されています。len関数を実行するとちょうど100になりました。最初に数えた通りですね。
音声を合成する
では、早速音声を合成していきましょう。
インタプリタにちまちま入力していきます。
指定する項目は読ませるテキストとスピードです。
音声形式はWAVとMP3で選べるみたいです。Pythonで処理できるのでWAVにします。
>>> import requests,pprint
>>> url = "https://api.nijivoice.com/api/platform/v1/voice-actors/1cae479f-715c-422a-9714-3510b4903780/generate-voice"
>>> payload = {
... "format": "wav",
... "script": "猫かわいい!にゃーん",
... "speed": "1.0"
... }
>>> headers = {
... "accept": "application/json",
... "x-api-key": "ここに自分のAPIキーを入れる",
... "content-type": "application/json"
... }
>>> resp = requests.post(url, json=payload, headers=headers)
>>> pprint.pprint(resp.json())
{'generatedVoice': {'audioFileDownloadUrl': 'ここにURLが入る',
'audioFileUrl': 'ここにURLが入る',
'duration': 2584,
'remainingCredits': 4990}}
おや?私はてっきりレスポンスボディはバイナリだと思っていましたが、どうやらクラウドに格納されるみたいですね。
残りの情報は音声の長さと残りの文字数みたいです。わざわざPythonで解析しなくても音声の長さが書いてあるのが非常にありがたい。
URLが2つあります。まぁダウンロードと書いてある方がきっとダウンロードするための方なんでしょう。
しかし、特に表記は見つけられませんでしたが、この音声いつまで残ってるんですかね?
というわけで続き
もう1回URLを叩いてコンテンツをダウンロード後、ファイルに保存します。
一旦バイナリを100バイトだけ表示してwavになってるか確認しています。
>>> URL = resp.json()["generatedVoice"]["audioFileDownloadUrl"]
>>> resp2 = requests.get(URL)
>>> resp2.content[:100]
b'RIFFRz\x03\x00WAVEfmt \x12\x00\x00\x00\x03\x00\x01\x00"V\x00\x00\x88X\x01\x00\x04\x00 \x00\x00\x00fact\x04\x00\x00\x00\x88\xde\x00\x00data z\x03\x00\xab>R\xb8B\xb1c7\xa59\xb88\x07t\x1382\x13&8T\xa7\x08\xb84;\x888\xdc\x16\xff7\x04\x1c\x8a8q\xcf\xd38\xa9g'
>>> f = open("nizi.wav","wb")
>>> f.write(resp2.content)
227930
>>> f.close()
生成した音声がこちら
VOICEVOXはイントネーション設定をしないと棒読みですが、さすがはAI何か感情がこもってますよ!。
音声: にじボイス (白石 玲奈)
プロパティはこちら
たかが2秒でやけにサイズがでかいなあ(222(にゃんにゃんにゃん)KB)。と思ったらビットレートがすごいですね。
クラスを作成する
私は今後、自分の読み上げツールにこちらも導入していく予定なのでクラスを作成します。
と言ってもこの前作ったvoicevoxモジュールコピペで追加するだけですが。
音声合成関数
中身をチラ見せするとこんな感じです。
インタプリタではrequestsライブラリを使っていましたが、DiscordのBOTなどのライブラリと組み合わせたい時は非同期になるのでaiohttpを使った実装に変更しています。
というわけで使用感はこんな感じ。
前作と同じように関数名や引数を合わせました。
こちらの場合は追加で残りの文字数がロギングされるようになりました。
今回制作したクラスはこの後の導入予定ツールの中に導入される予定です。
欲しい方はそちらをツールをダウンロードいただければ、一緒に入手することができる予定です。
>>> import voicevox
>>> nv = voicevox.NiziVoice(apikey="自分のキー",SaveDir="nizitest")
>>> nv.CreateWave("猫がかわいすぎて困るぅ",Cid="8c08fd5b-b3eb-4294-b102-a1da00f09c72")
2024-12-11 23:54:42,533 INFO voicevox 残り:4979文字です
{'path': 'nizitest\\00001_20241211_235441.wav', 'length': 2.241, 'text': '猫がかわいすぎて困るぅ', 'diff': 2.241, 'bin': None}
自作のクラスでした音声はこちら。当然ですが、全く問題なく生成できてますね。
音声: にじボイス (高槻 リコ)
ちなみにVOICEVOXの時と同様にlength引数で発言時間を指定して生成することもできます。
ただし、にじボイス自体が現段階で長さ指定に対応しているわけではないので、一度生成を行って時間を取得して、指定した長さに合わせるために必要なspeedを計算してから再生成します。
つまりコストは2倍かかりますので注意。
VOICEVOXでは5回まで試行しましたが、コストを考慮してこちらでは2回しか試行しないようにしています。
>>>nv.CreateWave("猫がかわいすぎて困るぅ",length=1.5)
キャラクター取得関数
キャラクターを取得する関数も追加しました。
こちらは現在VOICEVOXをベースにやっているのでそれの応答形式に合わせて返すようにしました。
>>>import voicevox
>>>nv = voicevox.NiziVoice(apikey="自分のキー")
>>>nizi.Getspeakers()
>>>pprint.pprint(nizi.speakers)
[{'name': '水戸 明日菜',
'speaker_uuid': 'ここにキャラクターIDが格納される',
'styles': [{'id': 'ここにキャラクターIDが格納される',
'name': 'ノーマル',
'type': 'talk'}]},
{'name': '漆夜 蓮',...
中身はこんな感じ。取得したJSONを再整形しているだけ。
導入済み/予定のツール
私が紹介している以下の作品でにじボイスに対応します。
全自動地声吹き替えツール
地声で収録した画面録画やスマートフォンの動画を読み上げ、実況に全自動コンバートするツール。
PowerPointのテキストボックスを字幕および読み上げ、文章としてアニメーション機能を活用して、動画としてエクスポートできるようにするアドインツール。
気になった点
最後ににじボイスサービスのどうしても気になっちゃう点について指摘しておこうと思います。
課金方式
生成した音声をやり直そうとしても既に課金済みというのが何というか納得いかないような。漢字読み間違いとかしたらどうするんでしょうか。MAXの500文字入れて間違ってましたやり直しで1000文字消費します!!って感じっぽいですね…。
今回採用している速度調整もですが、せめて生成直後にセッションIDとか配布して、N分以内にN回以内ならやり直せますよ的な感じにしてくれるとありがたいんですけど。
後はクレジットを入れる場所が無い時は読み上げが必要らしいんですが、それも課金クレジットを消費してクレジットを発言するっていうのがなんかなぁって感じ。それくらいキャラ一覧からファイル配布したら?って突っ込みたい。
そもそも有料サービスでクレジット入れるって見たことないんだがそういうものなのか?
まぁ規約に同意の上使っているので守るが指摘はしとく。
クレジットの有効期限
課金クレジットは5カ月が賞味期限だそうです。半年の6カ月じゃなくて5カ月なんだ。微妙だな。それだけ。
"."が読めない
「0.1秒」これを読ませると「れい 1びょう」とよくわからない空白ができます。
AI使ってるんですよね?"0.1"は"れいてんいち"ではないんですかね?
アルファベットが安定しない
例えば、"LinuxでPython使いたい"は正常に読めますが、"ArduinoでLED光らせる"は全くダメでした。LEDを"レッド"となんか無理やりな感じで読んできます。
これでも音声を生成しちゃえばもう課金済みなんですよね…。
スタイル
キャラ一覧を取得するとスタイルIDというのがあるがそれについて現段階でドキュメントでは使い方の言及がない。不明な要素。
まとめ
いかがでしたでしょうか?
今回は本日公開されたにじボイスのAPIを試してみました。
やはりAPIが使えるかどうかで利用の幅が全然違いますね。
気になる点はあるものの、まだ始まったばかりです。今後に期待ですね。
それではまたお会いしましょう。