rinna株式会社が提供しているText to Speech - v2のAPIをOracle APEXのアプリケーションから呼び出して、文章の読み上げを実装してみます。
音声の部分が再生されないため動作が分からないですが、Text to SpeechのボタンをクリックするとrinnaのAPIを呼び出し、文章の読み上げを行います。結果がWAVファイルとして生成されるので、それを取得しデータベースに保存します。オーディオ・コントロールより、データベースに保存したWAVファイルを再生します。
対話モード・レポートのページより、それまでのAPI呼び出しの履歴である文章とWAVにアクセスできます。ボイスIDやスタイルの影響について確認できます。
rinna株式会社の開発者向けサイトよりアカウント登録を行い、Rinna IDを取得します。取得したRinna IDのProfileから、APIの認証に使用するキー(Primary keyまたはSecondary key)の値を確認します。適用されているプランについては、Plansのタブから確認できます。2023年3月6日現在、Freeのプロダクトで月間1,000リクエストまで無料でAPIの呼び出しができるようです。
提供されているAPIのTerms of UseおよびFAQなどは、利用者ご自身にて確認していだくようお願いします。FAQには、APIは現在、試験運用中で検証を除く業務用利用は禁止しております、と記載されています。作成するOracle APEXのアプリケーションは、指定可能な各種のパラメータを設定してText To SpeechのAPIを呼び出します。生成されたWAVファイルを取得し、データベースにBLOBとして保存したのち再生します。
最初に、読み上げの元になる文章と音声データを保存する表を作成します。
クイックSQLの以下のモデルを使って、表RINNA_TEXT_TO_SPEECHESを作成します。列SID、TID、SPEED、VOLUMEはText to SpeechのAPI呼び出し時に与えるパラメータです。これ以外にMP3またはWAVのどちらかのフォーマットを指定できますが、今回のアプリケーションはWAVで固定します。
# prefix: rinna
# auditcols: true
text_to_speeches
text clob
speech blob
sid number
tid number
speed number
volume number
SQLの生成、SQLスクリプトを保存、レビューおよび実行を順次クリックします。表の作成までを実施し、アプリケーションの作成は行いません。
データベースの列SPEECHに保存されたWAVデータを再生するために、RESTサービス作成します。
SQLワークショップのRESTfulサービスを開きます。
モジュール名はrinna、ベース・パスは/rinna/とします。公開はONにします。
URLテンプレートはspeechとします。
完全なURLに引数idを与えることにより、列SPEECHに保存されたWAVデータが取り出されます。今回はAlways FreeのAutonomous Database上でアプリケーションを実装しているため、以下のようなURLになります。
ページ名はSpeechesとします。表またはビューとしてRINNA_TEXT_TO_SPEECHESを選択します。フォームは不要なので、フォームを含めるはチェックしません。
ハンドラを作成します。
メソッドはGET、ソース・タイプにMedia Resourceを選択します。ソースとして以下のSQLを記述します。
select 'audio/wav', speech from rinna_text_to_speeches where id = :id
https://ホスト名/ords/ワークスペース名/rinna/speech?id=表RINNA_TEXT_TO_SPEECHESのID値
rinna APIの認証に使用するWeb資格証明を作成します。
ワークスペース・ユーティリティのWeb資格証明を開きます。
rinna APIはHTTPヘッダーOcp-Apim-Subscription-KeyにPrimary key(またはSecondary key)を与えることで認証されます。
名前はrinna Developer key、静的識別子としてRINNA_DEVELOPER_KEYを設定します。静的識別子はPL/SQLコード中に埋め込みます。異なる静的識別子にした場合は、PL/SQLのコードも変更する必要があります。
認証タイプにHTTPヘッダー、資格証明名としてOcp-Apim-Subscription-Key、資格証明シークレットとしてrinna IDのProfileから確認できるPrimary keyを設定します。
以上で準備ができました。これからAPEXのアプリケーションを作成します。
アプリケーション作成ウィザードを起動し、空のアプリケーションを作成します。名前はText to Speechとします。
対話モード・レポートのページを追加します。ページの追加をクリックします。
対話モード・レポートを選択します。
ページの追加をクリックします。
アプリケーションの作成をクリックします。
最初に共有コンポーネントとして、スタイルIDを指定するためのLOVを作成します。
共有コンポーネントを開きます。
他のコンポーネントのLOVを開きます。
作成済みのLOVが一覧されます。作成をクリックします。
LOVの作成は最初からを選択します。
次へ進みます。
作成するLOVの名前はLOV_SYTLEとします。タイプはStaticを選択します。
次へ進みます。
LOVの表示値と戻り値を設定します。スタイルIDの定義より、'1:talk' or '2:happy' or '3:sad' or '5:angry' or '6:fear' or '7:surprised'を戻り値:表示値のペアとして設定します。
LOVの作成をクリックします。
共有LOVとしてLOV_STYLEが作成されました。
ホーム・ページにText to Speech APIの呼び出しを実装します。
ホーム・ページのページ・ナビゲーションを削除します。
ボイスIDを指定するページ・アイテムP1_SIDを作成します。
識別の名前はP1_SID、タイプは数値フィールド、ラベルはボイスIDとします。設定の最小値は27、最大値は47を設定します。検証の必須の値をONにします。デフォルトのタイプに静的値を選択し、静的値として27を設定します。
識別の名前はP1_TID、タイプは選択リスト、ラベルはスタイルとします。レイアウトの新規行の開始をOFFとして、ページ・アイテムP1_SIDの右隣に配置します。検証の必須の値はONとします。LOVのタイプに共有コンポーネントを選択し、LOVとして先ほど作成したLOV_SYTLEを選択します。デフォルトのタイプは静的、静的値に1を指定し、ニュートラルな話し方であるtalkをデフォルトにします。
話速を指定するページ・アイテムP1_SPEEDを作成します。
識別の名前はP1_SPEED、タイプは数値フィールド、ラベルは話速とします。設定の最小値は0.1、最大値は10.0、仮想キーボードにNumericを選択します。新規行の開始はOFFにして、ページ・アイテムP1_TIDの右隣に配置します。
検証の必須の値をON、デフォルトのタイプは静的、静的値として1.0を指定します。
音量を指定するページ・アイテムP1_VOLUMEを作成します。
識別の名前をP1_VOLUME、ラベルを音量とします。それ以外はP1_SPEEDと同じ設定を行います。
読み上げるテキストを入力するページ・アイテムP1_TEXTを作成します。
識別の名前はP1_TEXT、タイプとしてテキスト領域を選択します。検証の必須の値はONにします。
Text to Speechを実行するボタンを作成します。
識別のボタン名はTEXT_TO_SPEECH、ラベルはText to Speech、動作のアクションとして、デフォルトのページの送信を選択します。
APIを呼び出して取得した音声は、表RINNA_TEXT_TO_SPEECHESに保存されます。保存されている行の主キーの値を保存するページ・アイテムP1_IDを作成します。
識別の名前をP1_ID、タイプとして非表示を選択します。
リージョンを作成し、識別のタイトルを読み上げとします。タイプとして静的コンテンツを選択し、ソースのHTMLコードとして以下を記述します。WAVデータを取り出すORDS RESTサービスを呼び出します。/ords/apexdevの部分は環境に合わせて変更します。
<audio controls src="/ords/apexdev/rinna/speech?id=&P1_ID."></audio>
サーバー側の条件のボタン押下時にTEXT_TO_SPEECHを選択します。
外観のテンプレートにBlank with Attributesを選択します。サーバー側の条件のタイプとしてアイテムはNULLではないを選択し、アイテムにP1_IDを指定します。
ボタンTEXT_TO_SPEECHをクリックしたときに実行されるプロセスを作成します。
作成したプロセスの識別の名前はText to Speechとします。タイプはコードを実行です。ソースのPL/SQLコードとして、以下を記述します。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
declare | |
l_request json_object_t; | |
l_request_clob clob; | |
l_response json_object_t; | |
l_response_clob clob; | |
l_media_content_url varchar2(32767); | |
l_blob blob; | |
begin | |
/* | |
* Text To Speech V2のリクエストを作成する。 | |
* | |
* 参照: https://developers.rinna.co.jp/api-details#api=TextToSpeech-v2 | |
*/ | |
l_request := json_object_t(); | |
l_request.put('sid', to_number(:P1_SID)); | |
l_request.put('tid', to_number(:P1_TID)); | |
l_request.put('speed', to_number(:P1_SPEED)); | |
l_request.put('text', :P1_TEXT); | |
l_request.put('volume', to_number(:P1_VOLUME)); | |
l_request.put('format', 'wav'); | |
l_request_clob := l_request.to_clob(); | |
-- apex_debug.info(l_request_clob); | |
/* | |
* Text To Speech の呼び出し。 | |
*/ | |
apex_web_service.clear_request_headers; | |
apex_web_service.set_request_headers('Content-Type','application/json', p_reset => false); | |
apex_web_service.set_request_headers('Cache-Control','no-cache', p_reset => false); | |
l_response_clob := apex_web_service.make_rest_request( | |
p_url => 'https://api.rinna.co.jp/models/cttse/v2' | |
,p_http_method => 'POST' | |
,p_body => l_request_clob | |
,p_credential_static_id => 'RINNA_DEVELOPER_KEY' | |
); | |
if apex_web_service.g_status_code <> 200 then | |
raise_application_error(-20001, 'Text To Speech = ' || apex_web_service.g_status_code); | |
end if; | |
/* | |
* レスポンスから生成されたWAVファイルのURLを取得する。 | |
*/ | |
l_response := json_object_t(l_response_clob); | |
l_media_content_url := l_response.get_string('mediaContentUrl'); | |
if l_media_content_url is null then | |
raise_application_error(-20001, 'No MediaContentUrl'); | |
end if; | |
/* | |
* WAVファイルを取得し、BLOBとして保存する。 | |
*/ | |
apex_web_service.clear_request_headers; | |
apex_web_service.set_request_headers('Content-Type','audio/wav', p_reset => false); | |
l_blob := apex_web_service.make_rest_request_b( | |
p_url => l_media_content_url | |
,p_http_method => 'GET' | |
,p_credential_static_id => 'RINNA_DEVELOPER_KEY' | |
); | |
if apex_web_service.g_status_code <> 200 then | |
raise_application_error(-20001, 'Get Speech = ' || apex_web_service.g_status_code); | |
end if; | |
/* | |
* テキストと音声の両方を保存する。 | |
*/ | |
insert into rinna_text_to_speeches(text, speech, sid, tid, speed, volume) | |
values(:P1_TEXT, l_blob, :P1_SID, :P1_TID, :P1_SPEED, :P1_VOLUME) | |
returning id into :P1_ID; | |
end; |
Text to Speechの実行履歴を一覧するレポートより、保存されている音声を再生できるようにします。
列IDのタイプをプレーン・テキストに変更し、列の書式のHTML式として以下を記述します。/ords/apexdevの部分は環境に合わせて変更します。
<audio controls src="/ords/apexdev/rinna/speech?id=#ID#"></audio>
列TIDを選択し、識別のタイプをプレーン・テキスト(LOVに基づく)に変更します。LOVとしてLOV_STYLEを選択します。
以上でアプリケーションは完成です。
今回作成したAPEXアプリケーションのエクスポートを以下に置きました。
https://github.com/ujnak/apexapps/blob/master/exports/text-to-speech.zip
Oracle APEXのアプリケーション作成の参考になれば幸いです。
完