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ブラウザで開きます。 モダンなブラウザなら多分開けるでしょう。
話者のプルダウンを選択すると、その話者のパラメタ入力欄が動的に生成されます。なお、以前のパラメタ値を覚えているような作りにはなっていませんので注意してください。
また、入力値に対するエラーチェックは省いてます。気になったら利用者自身で追加してください。
設定2タブの設定を書き換えます。
設定が終わったら利用可能話者タブのサービス開始/再始動ボタンを押してください。
C:\Work\appフォルダには SeikaSan.jsが入っています。これを開いて、
を自分のSeikaCenterの設定に合わせて書き換えます。
以下は20190428/u に同梱されている 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);
}
}
以下は20190428/u に同梱されている 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>
SeikaSan.js の以下の行をtrueにするとSeikaCenterを実行しているPCで音声再生となり、falseにすると、seikasanjs.htmlを表示しているWebブラウザを実行しているPCで音声再生します。
var playswitch = false;