优化:公屏预加载叫号音频素材 #3
@@ -1,5 +1,10 @@
|
|||||||
import { describe, expect, it } from "vitest";
|
import { renderHook } from "@testing-library/react";
|
||||||
import { announcementAudioQueue } from "./useAudioAnnouncements";
|
import { afterEach, describe, expect, it } from "vitest";
|
||||||
|
import { announcementAudioQueue, audioPreloadSources, useAudioAnnouncements } from "./useAudioAnnouncements";
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
document.head.querySelectorAll("link[data-queue-voice-preload]").forEach((link) => link.remove());
|
||||||
|
});
|
||||||
|
|
||||||
describe("announcementAudioQueue", () => {
|
describe("announcementAudioQueue", () => {
|
||||||
it("忽略项目名并把单号码播报素材重复三遍", () => {
|
it("忽略项目名并把单号码播报素材重复三遍", () => {
|
||||||
@@ -34,4 +39,15 @@ describe("announcementAudioQueue", () => {
|
|||||||
"/audio/queue-voice/entrance.wav",
|
"/audio/queue-voice/entrance.wav",
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("打开页面时预加载全部声音素材", () => {
|
||||||
|
const { unmount } = renderHook(() => useAudioAnnouncements());
|
||||||
|
const links = Array.from(document.head.querySelectorAll<HTMLLinkElement>("link[data-queue-voice-preload]"));
|
||||||
|
|
||||||
|
expect(links.map((link) => link.getAttribute("href"))).toEqual(audioPreloadSources);
|
||||||
|
expect(links.every((link) => link.rel === "preload" && link.getAttribute("as") === "audio")).toBe(true);
|
||||||
|
|
||||||
|
unmount();
|
||||||
|
expect(document.head.querySelector("link[data-queue-voice-preload]")).toBeNull();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -24,6 +24,12 @@ const PHRASE_AUDIO = [
|
|||||||
["至", `${AUDIO_BASE_PATH}/through.wav`],
|
["至", `${AUDIO_BASE_PATH}/through.wav`],
|
||||||
] as const;
|
] as const;
|
||||||
|
|
||||||
|
export const audioPreloadSources = [
|
||||||
|
...Object.values(DIGIT_AUDIO),
|
||||||
|
...PHRASE_AUDIO.map(([, source]) => source),
|
||||||
|
GAP_AUDIO,
|
||||||
|
];
|
||||||
|
|
||||||
function clipsForAnnouncement(announcement: string): string[] {
|
function clipsForAnnouncement(announcement: string): string[] {
|
||||||
const callStart = announcement.indexOf("请");
|
const callStart = announcement.indexOf("请");
|
||||||
if (callStart < 0) return [];
|
if (callStart < 0) return [];
|
||||||
@@ -61,6 +67,23 @@ export function useAudioAnnouncements() {
|
|||||||
const audioRef = useRef<HTMLAudioElement | null>(null);
|
const audioRef = useRef<HTMLAudioElement | null>(null);
|
||||||
const playbackIdRef = useRef(0);
|
const playbackIdRef = useRef(0);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (typeof document === "undefined") return;
|
||||||
|
|
||||||
|
const links = audioPreloadSources.map((source) => {
|
||||||
|
const link = document.createElement("link");
|
||||||
|
link.rel = "preload";
|
||||||
|
link.setAttribute("as", "audio");
|
||||||
|
link.type = "audio/wav";
|
||||||
|
link.href = source;
|
||||||
|
link.dataset.queueVoicePreload = "true";
|
||||||
|
document.head.appendChild(link);
|
||||||
|
return link;
|
||||||
|
});
|
||||||
|
|
||||||
|
return () => links.forEach((link) => link.remove());
|
||||||
|
}, []);
|
||||||
|
|
||||||
const playQueue = useCallback((sources: string[]) => {
|
const playQueue = useCallback((sources: string[]) => {
|
||||||
const audio = audioRef.current;
|
const audio = audioRef.current;
|
||||||
if (!audio || !sources.length) return;
|
if (!audio || !sources.length) return;
|
||||||
|
|||||||
Reference in New Issue
Block a user