后端 TTS 以 data: URI 返回 base64 mp3(生产实证为合法 LAME mp3),但 App-Plus 的 InnerAudioContext 不支持 data: URI,iOS Safari/微信 webview 也常静默失败,统一报"语音播放失败"。播放前按平台转换:H5 转 Blob URL, App 端经 plus.io 落 _doc/ 临时文件后播放 file:// 路径,播完清理;Blob 不可 用时退回原始 data: URI。竞态守卫与缓存语义保持不变,158 单测全绿。
120 lines
4.0 KiB
JavaScript
120 lines
4.0 KiB
JavaScript
import assert from 'node:assert/strict';
|
|
import { readFile } from 'node:fs/promises';
|
|
import test from 'node:test';
|
|
import vm from 'node:vm';
|
|
import ts from 'typescript';
|
|
|
|
const loadModule = async (sandbox = {}) => {
|
|
const service = await readFile(new URL('../src/services/speech-audio-source.ts', import.meta.url), 'utf8');
|
|
const compiled = ts.transpileModule(service, {
|
|
compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2020 }
|
|
});
|
|
const runtimeModule = { exports: {} };
|
|
vm.runInNewContext(compiled.outputText, {
|
|
exports: runtimeModule.exports,
|
|
module: runtimeModule,
|
|
atob: (value) => Buffer.from(value, 'base64').toString('binary'),
|
|
Blob,
|
|
URL,
|
|
Date,
|
|
...sandbox
|
|
});
|
|
return runtimeModule.exports;
|
|
};
|
|
|
|
// 'ID3' 是 mp3 文件头标识,base64 为 SUQz
|
|
const MP3_DATA_URI = `data:audio/mp3;base64,${Buffer.from('ID3 |