ユーザ用ツール

サイト用ツール


seikacenter-200

差分

このページの2つのバージョン間の差分を表示します。

この比較画面へのリンク

両方とも前のリビジョン前のリビジョン
次のリビジョン
前のリビジョン
seikacenter-200 [2023/04/13 00:45] – 削除 - 外部編集 (Unknown date) 127.0.0.1seikacenter-200 [2025/03/30 02:01] (現在) – 外部編集 127.0.0.1
行 1: 行 1:
 +====== HTTP機能利用例 ======
 +
 +SeikaCenterのサポートは終了いたしました。\\ この製品に修正や機能拡張は今後行われません。現時点での最新版のダウンロードは可能です。\\
 +後継プロダクト AssistantSeika をご利用ください。
 +
 +SeikaCenterをWebブラウザのJavaScriptで操作するサンプルWebアプリケーション SeikaSanJS の説明。
 +
 +
 +
 +===== 概要 =====
 +
 +SeikaCenter 20190428/u 以降に追加した、簡易Webサーバ機能とHTTP機能を使って、WebブラウザからSeikaCenterを制御するアプリケーションです。
 +
 +===== 実行例 =====
 +
 +HTTP機能で設定したURL http://192.168.1.100:7180/app/seikasanjs.html をWebブラウザで開きます。
 +モダンなブラウザなら多分開けるでしょう。
 +
 +話者のプルダウンを選択すると、その話者のパラメタ入力欄が動的に生成されます。なお、以前のパラメタ値を覚えているような作りにはなっていませんので注意してください。
 +
 +また、入力値に対するエラーチェックは省いてます。気になったら利用者自身で追加してください。
 +{{pasted:20230411-194755.png?nolink}}
 +{{pasted:20230411-194809.png?nolink}}
 +{{pasted:20230411-194818.png?nolink}}
 +
 +===== 設定 =====
 +
 +==== SeikaCenter設定 ====
 +
 +設定2タブの設定を書き換えます。
 +
 +  * 待ち受けアドレスには、SeikaCenterを実行しているPCに割り当てたIPアドレスを入力します。この例では "192.168.1.100" になっています。
 +  * Access-Control-Allow-Origin は、待ち受けアドレスと待ち受けポートからURLを作ります。この例では "http://192.168.1.100:7180" になっています。
 +  * 配布アーカイブに含まれる、app フォルダを、丸ごとワークフォルダへコピーします。この例ではワークフォルダが "C:\Work"なので、 "C:\Work\app" にコピーすることになります。
 +
 +設定が終わったら利用可能話者タブのサービス開始/再始動ボタンを押してください。
 +
 +{{pasted:20230411-194845.png?nolink}}
 +
 +==== SeikaSan.js 書き換え ====
 +
 +C:\Work\appフォルダには SeikaSan.jsが入っています。これを開いて、
 +  * var id          = "SeikaServerUser";
 +  * var pass        = "SeikaServerPassword";
 +  * var url         = "http://192.168.1.100:7180";
 +
 +を自分のSeikaCenterの設定に合わせて書き換えます。
 +
 +以下は20190428/u に同梱されている SeikaSan.jsです。
 +
 +<code js SeikaSan.js>
 +// 単にPCの音声合成製品を発声させるだけならこちら true, ブラウザを実行している機器で再生するなら false
 +var playswitch  = false;
 +var headers     = new Headers();
 +var fetchopt    = { mode: 'cors', credentials: 'include' };
 +var id          = "SeikaServerUser";
 +var pass        = "SeikaServerPassword";
 +var url         = "http://192.168.1.100:7180";
 +var sampleRate  = 8000;
 +var audioCtx = new (window.AudioContext || window.webkitAudioContext)();
 +var paramJson;
 +
 +function initcode()
 +{
 +    headers.set('Authorization', 'Basic ' +  btoa(unescape(encodeURIComponent( id + ":" + pass ))) );
 +    headers.set('Content-Type',  'application/json');
 +    fetchopt.headers = headers;
 +    document.getElementById('cid').addEventListener('change',MakeEffectPanel);
 +    document.getElementById('btn').addEventListener('click',Talk);
 +}
 +
 +function MakeTalkParam()
 +{
 +    var body = {};
 +
 +    body.talktext = document.getElementById('talktext').value;
 +    body.effects   = {};
 +    for(let propName in paramJson.effect)
 +    {
 +        body.effects[propName] = parseFloat(document.getElementById(propName).value);
 +    }
 +    if ("emotion" in paramJson)
 +    {
 +        body.emotions = {};
 +        for(let propName in paramJson.emotion)
 +        {
 +            body.emotions[propName] = parseFloat(document.getElementById(propName).value);
 +        }
 +    }
 +
 +    return body;
 +}
 +
 +async function Talk()
 +{
 +    var cid = document.getElementById('cid');
 +    var btn = document.getElementById('btn');
 +
 +    fetchopt.method  = 'POST';
 +    fetchopt.body    = JSON.stringify(MakeTalkParam());
 +    btn.disabled = true;
 +
 +    if (playswitch)
 +    {
 +        const res  = await fetch(url + "/PLAY2/" + cid.options[cid.selectedIndex].value , fetchopt);
 +        const json = await res.json();
 +    }
 +    else
 +    {
 +      const res  = await fetch(url + "/SAVE2/" + cid.options[cid.selectedIndex].value + "/" + sampleRate , fetchopt);
 +      const wavbuff = await res.arrayBuffer();
 +      var audioBuffer = await audioCtx.decodeAudioData(wavbuff);
 +      var source = audioCtx.createBufferSource();
 +      source.buffer = audioBuffer;
 +      source.loop      = false;
 +      source.loopStart = false;
 +      source.loopEnd   = audioBuffer.duration;
 +      source.connect(audioCtx.destination);
 +      source.start(0);
 +    }
 +
 +    btn.disabled = false;
 +}
 +
 +async function MakeAvatorList()
 +{
 +    fetchopt.method  = 'GET';
 +    fetchopt.body    = null;
 +    const res  = await fetch(url+"/AVATOR2", fetchopt);
 +    const json = await res.json();
 +
 +    var sel = document.getElementById('cid');
 +    sel.disabled = true;
 +    for(let idx=0; idx<json.length; idx++)
 +    {
 +         sel.options.add( new Option( json[idx].cid + ' : ' + json[idx].name, json[idx].cid ) );
 +    }
 +    sel.disabled = false;
 +    MakeEffectPanel();
 +}
 +
 +async function MakeEffectPanel()
 +{
 +    var sel = document.getElementById('cid');
 +    var cid = sel.options[sel.selectedIndex].value;
 +    fetchopt.method  = 'GET';
 +    fetchopt.body    = null;
 +    const res  = await fetch(url+"/AVATOR2/"+cid, fetchopt);
 +    paramJson = await res.json();
 +
 +    var p300 = document.getElementById('p300');
 +    var s    = p300.childNodes.length;
 +    for(let idx=0; idx < s; idx++)
 +    {
 +        p300.removeChild(p300.firstChild);
 +    }
 +
 +    for(let propName in paramJson.effect)
 +    {
 +        var item = paramJson.effect[propName];
 +        var p1 = document.createTextNode(propName + ': ');
 +        var p2 = document.createElement('input');
 +        var p3 = document.createTextNode(' range ' + item.min + ' ~ ' + item.max + ', step ' + item.step);
 +        var p4 = document.createElement('br');
 +        p300.appendChild(p1);
 +        p300.appendChild(p2);
 +        p2.value = item.value;
 +        p2.id = propName;
 +        p300.appendChild(p3);
 +        p300.appendChild(p4);
 +    }
 +
 +    for(let propName in paramJson.emotion)
 +    {
 +        var item = paramJson.emotion[propName];
 +        var p1 = document.createTextNode(propName + ': ');
 +        var p2 = document.createElement('input');
 +        var p3 = document.createTextNode(' range ' + item.min + ' ~ ' + item.max + ', step ' + item.step);
 +        var p4 = document.createElement('br');
 +        p300.appendChild(p1);
 +        p300.appendChild(p2);
 +        p2.value = item.value;
 +        p2.id = propName;
 +        p300.appendChild(p3);
 +        p300.appendChild(p4);
 +    }
 +}
 +</code>
 +
 +以下は20190428/u に同梱されている seikasanjs.html です。 
 +
 +<code html seikasanjs.html>
 +<!doctype html>
 +<html>
 +  <head>
 +    <meta charset="utf-8"/>
 +    <title>SeikaSanJS</title>
 +    <script src="SeikaSan.js"></script>
 +  </head>
 +  <body>
 +    <h1>SeikaSanJS</h1>
 +    <fieldset>
 +        <legend>話者</legend>
 +        <select id="cid"></select>
 +    </fieldset>
 +    <fieldset>
 +        <legend>テキスト</legend>
 +        <textarea id="talktext" rows="5" cols="40"></textarea>
 +    </fieldset>
 +    <button id="btn">再生</button>
 +    <fieldset>
 +        <legend>パラメタ</legend>
 +        <div id="p300">
 +        </div>
 +    </fieldset>
 +    <script>
 +        initcode();
 +        MakeAvatorList();
 +    </script>
 +  </body>
 +</html>
 +</code>
 +
 +
 +===== 音声再生場所の変更 =====
 +
 +SeikaSan.js の以下の行をtrueにするとSeikaCenterを実行しているPCで音声再生となり、falseにすると、seikasanjs.htmlを表示しているWebブラウザを実行しているPCで音声再生します。
 +
 +<code>var playswitch  = false;</code>
 +
 +{{tag> 技術資料 Windows Voiceroid2 CeVIO }}
 +
  

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki