feat(mobile): expand TTS voices and align App SDK

This commit is contained in:
2026-07-26 17:05:43 +08:00
parent 94ee29f59c
commit f57e0a53c6
18 changed files with 1171 additions and 419 deletions
+22 -1
View File
@@ -2,7 +2,8 @@ import type { AsrResponse, PracticeTtsContext, SpeechPlaybackStatus, SpeechSelec
import { apiRequest, apiUrl, authHeaders, readTextPayload } from './api';
import { getAuth } from './auth';
import type { SpeechCapture } from './speech-capture';
import { dataUriToBlobUrl, hasNativeAudioFileSupport, isDataAudioUri, removeNativeTempAudio, writeNativeTempAudio } from './speech-audio-source';
import { estimateMpegAudioDuration } from './mpeg-audio-duration';
import { dataUriToBlobUrl, decodeDataAudioUri, hasNativeAudioFileSupport, isDataAudioUri, removeNativeTempAudio, writeNativeTempAudio } from './speech-audio-source';
import { applyTtsVoicePreference, getTtsDialectPreference, getTtsVoicePreference } from './tts-voice-preference';
const audioExtensions = ['.mp3', '.wav', '.m4a', '.webm', '.aac', '.ogg'];
@@ -344,8 +345,28 @@ export const createSpeechPlaybackController = (
return { toggle, stop, destroy, preload };
};
/**
* data: URI 直接数帧,不经宿主音频 API。
*
* App-Plus 的逻辑层是 JsCore,没有 `Audio`,原先在这里直接返回 null,
* 导致语音条只显示「语音」而没有秒数。字节解析在 H5 上同样可用且更快,
* 所以两端都优先走它,`Audio` 只作为远端 URL 的兜底。
*/
const measureFromBytes = (source: string): number | null => {
if (!isDataAudioUri(source)) return null;
const decoded = decodeDataAudioUri(source);
if (!decoded) return null;
const seconds = estimateMpegAudioDuration(decoded.bytes);
return seconds ? Math.max(1, Math.round(seconds)) : null;
};
export const measureAudioDuration = (source: string): Promise<number | null> =>
new Promise((resolve) => {
const fromBytes = measureFromBytes(source);
if (fromBytes !== null) {
resolve(fromBytes);
return;
}
if (typeof Audio === 'undefined') {
resolve(null);
return;