Commit 9a27099e authored by martin hou's avatar martin hou

fix: 适配16k采样率的实时音频流

parent dbc24bdd
...@@ -491,13 +491,14 @@ export function Home() { ...@@ -491,13 +491,14 @@ export function Home() {
const totalFrames = Math.floor((u8.length - 8) / 4); const totalFrames = Math.floor((u8.length - 8) / 4);
if (totalFrames <= 0) return [0, 0, new Uint8Array(0)]; if (totalFrames <= 0) return [0, 0, new Uint8Array(0)];
// 48k -> 16k,降采样因子为3 // 48k -> 16k,降采样因子为3
const downFactor = 3; const downFactor = 1;
const outFrames = Math.floor((totalFrames + downFactor - 1) / downFactor) * 2; // 向上取整 const outFrames = totalFrames;
let sumL = 0; let sumL = 0;
let sumR = 0; let sumR = 0;
const mono8 = new Uint8Array(outFrames + 8); const mono8 = new Uint8Array(outFrames * 2 + 8);
let j = 0, k = 0; console.log('sampling', outFrames, u8.byteLength);
for (let i = 8; i + 3 < u8.length; i += 4, j++) let k = 0;
for (let i = 8; i + 3 < u8.length; i += 4)
{ {
const a = u8[i + 0] & 0xff; const a = u8[i + 0] & 0xff;
const b = u8[i + 1] & 0xff; const b = u8[i + 1] & 0xff;
...@@ -513,18 +514,15 @@ export function Home() { ...@@ -513,18 +514,15 @@ export function Home() {
const nr = r / 32768; const nr = r / 32768;
sumL += nl * nl; sumL += nl * nl;
sumR += nr * nr; sumR += nr * nr;
// 双声道合成为单声道(16-bit),再压缩为 Int8 // 双声道合成为单声道;双静音直接归零避免底噪,其他情况用平均叠加
// C = A + B - (A * B / 32767) const nearSilent = Math.abs(l) < 4 && Math.abs(r) < 4;
if (j % downFactor == 0) let m = nearSilent ? 0 : (l + r) / 2;
{ if (m > 32767) m = 32767;
let m = l + r - Math.floor((l * r) / 32767); else if (m < -32768) m = -32768;
if (m > 32767) m = 32767; const H = (m >> 8) & 0xff;
else if (m < -32768) m = -32768; const L = m & 0xff;
let H = (m >> 8) & 0xff; mono8[8 + k++] = L;
let L = m & 0xff; mono8[8 + k++] = H;
mono8[8 + k++] = (L << 8);
mono8[8 + k++] = H;
}
} }
const leftRms = Math.sqrt(sumL / totalFrames); const leftRms = Math.sqrt(sumL / totalFrames);
const rightRms = Math.sqrt(sumR / totalFrames); const rightRms = Math.sqrt(sumR / totalFrames);
...@@ -533,6 +531,7 @@ export function Home() { ...@@ -533,6 +531,7 @@ export function Home() {
} }
const blocksRef = useRef<Uint8Array[]>([]); const blocksRef = useRef<Uint8Array[]>([]);
const scheduleLiveTick = async () => { const scheduleLiveTick = async () => {
let jensen = getJensen(); let jensen = getJensen();
if (jensen == null) return; if (jensen == null) return;
...@@ -569,10 +568,12 @@ export function Home() { ...@@ -569,10 +568,12 @@ export function Home() {
liveTimeoutRef.current = window.setTimeout(scheduleLiveTick, 100); liveTimeoutRef.current = window.setTimeout(scheduleLiveTick, 100);
// 开启发送音频定时器 // 开启发送音频定时器
/*
if (sendTimeoutRef.current !== null) { if (sendTimeoutRef.current !== null) {
window.clearTimeout(sendTimeoutRef.current); window.clearTimeout(sendTimeoutRef.current);
} }
sendTimeoutRef.current = window.setTimeout(sendLiveAudio, 100); sendTimeoutRef.current = window.setTimeout(sendLiveAudio, 100);
*/
} }
function stringToUuidBytes(str: string): Uint8Array { function stringToUuidBytes(str: string): Uint8Array {
...@@ -620,8 +621,8 @@ export function Home() { ...@@ -620,8 +621,8 @@ export function Home() {
// 创建一个websocket实例 // 创建一个websocket实例
const wsRef = useRef<WebSocket | null>(null); const wsRef = useRef<WebSocket | null>(null);
const startLiveSession = async () => { const startLiveSession = async () => {
if (new Date().getTime() > 0) return startSession();
const token = 'kL5NmbPEGOptIGbt8jtR3pjXVHT9p774n7N4oQAARb0ctUMnq4bABgBPZ7QjYSUi'; const token = 'O9UkcTQg1l9HbKocNuNVplRhI3q7JdTRiQAP5j3zjSFNQ2yRd3crH0HrDfRDP7TH';
let url = 'wss://live.test.hidock.com/ws/realtime?accesstoken=' + token + '&mode=room&language=cmn&'; let url = 'wss://live.test.hidock.com/ws/realtime?accesstoken=' + token + '&mode=room&language=cmn&';
// wss://live.test.hidock.com/ws/realtime?accesstoken=&mode=room&language=cmn // wss://live.test.hidock.com/ws/realtime?accesstoken=&mode=room&language=cmn
wsRef.current = new WebSocket(url); wsRef.current = new WebSocket(url);
...@@ -657,11 +658,11 @@ export function Home() { ...@@ -657,11 +658,11 @@ export function Home() {
} }
if (data.type == 'partial') if (data.type == 'partial')
{ {
console.log('live', data.text); console.log('live-text', data.text);
} }
if (data.type == 'final') if (data.type == 'final')
{ {
console.log('live', data.text); console.log('live-text', data.text);
} }
} }
wsRef.current.onerror = (event) => { wsRef.current.onerror = (event) => {
...@@ -688,14 +689,13 @@ export function Home() { ...@@ -688,14 +689,13 @@ export function Home() {
window.clearTimeout(liveTimeoutRef.current); window.clearTimeout(liveTimeoutRef.current);
liveTimeoutRef.current = null; liveTimeoutRef.current = null;
} }
console.log('live stopped'); Logger.info('jensen', 'live', 'live stopped');
/* const totalSamples = blocksRef.current.reduce((sum, arr) => sum + arr.length - 8, 0);
const totalSamples = blocksRef.current.reduce((sum, arr) => sum + arr.length, 0);
const monoAll = new Uint8Array(totalSamples); const monoAll = new Uint8Array(totalSamples);
let offsetMono = 0; let offsetMono = 0;
for (const arr of blocksRef.current) { for (const arr of blocksRef.current) {
monoAll.set(arr, offsetMono); monoAll.set(arr.slice(8), offsetMono);
offsetMono += arr.length; offsetMono += arr.length - 8;
} }
let blob = new Blob([monoAll.buffer], { type: 'audio/pcm' }); let blob = new Blob([monoAll.buffer], { type: 'audio/pcm' });
let url = URL.createObjectURL(blob); let url = URL.createObjectURL(blob);
...@@ -704,7 +704,6 @@ export function Home() { ...@@ -704,7 +704,6 @@ export function Home() {
a.download = 'live.pcm'; a.download = 'live.pcm';
a.click(); a.click();
URL.revokeObjectURL(url); URL.revokeObjectURL(url);
*/
} }
return ( return (
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment