59 lines
2.0 KiB
TypeScript
59 lines
2.0 KiB
TypeScript
import type { SpeechCapabilitiesResponse } from "../../../server/src/api-types"
|
|
import type { SpeechPlaybackMode, SpeechTtsFormat } from "../stores/preferences"
|
|
|
|
export interface SpeechPlaybackSupportResult {
|
|
available: boolean
|
|
reason?: "unsupported-environment" | "provider-streaming-unavailable" | "browser-streaming-unavailable"
|
|
}
|
|
|
|
export function formatToMimeType(format: SpeechTtsFormat): string {
|
|
if (format === "wav") return "audio/wav"
|
|
if (format === "opus") return getSupportedMimeType(format)
|
|
if (format === "aac") return "audio/aac"
|
|
return "audio/mpeg"
|
|
}
|
|
|
|
export function getCandidateMimeTypes(format: SpeechTtsFormat): string[] {
|
|
if (format === "wav") return ["audio/wav"]
|
|
if (format === "opus") {
|
|
return ['audio/ogg; codecs="opus"', 'audio/webm; codecs="opus"', "audio/opus"]
|
|
}
|
|
if (format === "aac") return ["audio/aac", "audio/mp4", 'audio/mp4; codecs="mp4a.40.2"']
|
|
return ["audio/mpeg"]
|
|
}
|
|
|
|
export function getSupportedMimeType(format: SpeechTtsFormat): string {
|
|
const candidates = getCandidateMimeTypes(format)
|
|
if (typeof MediaSource === "undefined") {
|
|
return candidates[0]
|
|
}
|
|
return candidates.find((candidate) => MediaSource.isTypeSupported(candidate)) ?? candidates[0]
|
|
}
|
|
|
|
export function getSpeechPlaybackSupport(options: {
|
|
playbackMode: SpeechPlaybackMode
|
|
ttsFormat: SpeechTtsFormat
|
|
capabilities?: SpeechCapabilitiesResponse | null
|
|
}): SpeechPlaybackSupportResult {
|
|
if (typeof window === "undefined" || typeof window.Audio === "undefined") {
|
|
return { available: false, reason: "unsupported-environment" }
|
|
}
|
|
|
|
if (options.playbackMode !== "streaming") {
|
|
return { available: true }
|
|
}
|
|
|
|
if (!options.capabilities?.supportsStreamingTts) {
|
|
return { available: false, reason: "provider-streaming-unavailable" }
|
|
}
|
|
|
|
if (
|
|
typeof MediaSource === "undefined" ||
|
|
!getCandidateMimeTypes(options.ttsFormat).some((candidate) => MediaSource.isTypeSupported(candidate))
|
|
) {
|
|
return { available: false, reason: "browser-streaming-unavailable" }
|
|
}
|
|
|
|
return { available: true }
|
|
}
|