server.js を3点変更しました:
locale: 'ja-JP' → locale: ''(ローカルPCで成功していた設定) Content-Length ヘッダーを除去(test_tts.js では送っていなかった、これが差異の一つ) デバッグログを追加(Amazonへのリクエスト内容とレスポンスをログ出力) 認証問題について test_tts.js(ローカルで成功)と server.js(サーバーで失敗)を比較した結果、実は使っているCookieは全く同じもの(.env から読み込んでいる)なので、認証情報自体の差は本来ないはずです。 ただし、気になる点が1つあります: test_tts.js は locale: 'ja-JP' でローカルから成功しているのに、server.js は locale: 'ja-JP' でサーバーから失敗している これは実は「どこから接続しているか(IPアドレス) で Amazon 側の挙動が変わっている」可能性を示唆します。ただし、先ほど確認したように keinafarm.net は大阪のIPなので、この説明も矛盾します。 デプロイ手順: bash # ローカルから scp でサーバーへ転送 scp alexa-api/server.js keinafarm-claude:/home/claude/alexa-api/server.js # サーバーへSSHしてビルド&再起動 ssh keinafarm-claude 'cd /home/claude/alexa-api && sudo docker compose build && sudo docker compose up -d && sudo docker restart traefik' デプロイ後、sudo docker logs alexa_api -f でログを確認して、[DEBUG] 行の内容を教えてください。どんな JSON が Amazon に送られているか、Amazon が何を返しているかが見えてきます。
This commit is contained in:
@@ -37,6 +37,7 @@ function httpsRequest(path, options, extraCookies) {
|
||||
extraCookies = extraCookies || '';
|
||||
return new Promise(function(resolve, reject) {
|
||||
var allCookies = ALEXA_COOKIE + (extraCookies ? '; ' + extraCookies : '');
|
||||
// bodyBuf はバイト列変換(マルチバイト文字に対応)
|
||||
var bodyBuf = options.body ? Buffer.from(options.body, 'utf8') : null;
|
||||
var reqOpts = {
|
||||
hostname: ALEXA_HOST,
|
||||
@@ -47,7 +48,8 @@ function httpsRequest(path, options, extraCookies) {
|
||||
'Accept': 'application/json, text/plain, */*',
|
||||
'Accept-Language': 'ja-JP,ja;q=0.9',
|
||||
'Cookie': allCookies,
|
||||
}, bodyBuf ? { 'Content-Length': bodyBuf.length } : {}, options.headers || {}),
|
||||
// Content-Length は送らない(test_tts.js で動作実績あり、Amazonが自動判定)
|
||||
}, options.headers || {}),
|
||||
};
|
||||
var req = https.request(reqOpts, function(res) {
|
||||
var body = '';
|
||||
@@ -128,8 +130,8 @@ app.post('/speak', async function(req, res) {
|
||||
|
||||
console.log(' -> ' + target.accountName + ' (type=' + target.deviceType + ', serial=' + target.serialNumber + ')');
|
||||
|
||||
var ssml = '<speak>' + text + '</speak>';
|
||||
|
||||
// locale: '' はローカルPCでは日本語発話成功(サーバーからは要検証)
|
||||
// Alexa.SpeakSsml 系は全滅のため Alexa.Speak に戻す
|
||||
var sequenceObj = {
|
||||
'@type': 'com.amazon.alexa.behaviors.model.Sequence',
|
||||
startNode: {
|
||||
@@ -139,7 +141,7 @@ var sequenceObj = {
|
||||
deviceType: target.deviceType,
|
||||
deviceSerialNumber: target.serialNumber,
|
||||
customerId: customerId,
|
||||
locale: 'ja-JP',
|
||||
locale: '',
|
||||
textToSpeak: text
|
||||
},
|
||||
},
|
||||
@@ -151,6 +153,9 @@ var sequenceObj = {
|
||||
status: 'ENABLED',
|
||||
});
|
||||
|
||||
// リクエストボディをログ出力(認証・パラメータ確認用)
|
||||
console.log('[DEBUG] sequenceJson:', JSON.stringify(sequenceObj, null, 2));
|
||||
|
||||
var ttsRes = await httpsRequest('/api/behaviors/preview', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
@@ -162,6 +167,9 @@ var sequenceObj = {
|
||||
body: bodyStr,
|
||||
}, 'csrf=' + csrfToken);
|
||||
|
||||
// Amazonからのレスポンスをログ出力
|
||||
console.log('[DEBUG] Alexa API response: ' + ttsRes.status + ' body=' + ttsRes.body.substring(0, 200));
|
||||
|
||||
if (ttsRes.status === 200 || ttsRes.status === 202) {
|
||||
console.log(' [OK] TTS sent to ' + target.accountName);
|
||||
res.json({ ok: true, device: target.accountName, text: text });
|
||||
|
||||
Reference in New Issue
Block a user