feat(web): 实时对话 - 第一阶段输入行内联语音录制与浏览器 STT 转写 (#165)
Co-authored-by: zhaoyue <zhaoyue@rongshantech.com>
This commit is contained in:
69
web/src/components/conversation/audio-waveform.tsx
Normal file
69
web/src/components/conversation/audio-waveform.tsx
Normal file
@@ -0,0 +1,69 @@
|
||||
import { useMemo } from "react";
|
||||
|
||||
type AudioWaveformProps = {
|
||||
waveform: number[];
|
||||
/** 波形颜色,默认使用 CSS 变量 */
|
||||
color?: string;
|
||||
/** 波形高度(像素),默认 48 */
|
||||
height?: number;
|
||||
/** 波形宽度(像素),默认 200 */
|
||||
width?: number;
|
||||
/** 是否动画,默认 true */
|
||||
animated?: boolean;
|
||||
};
|
||||
|
||||
/**
|
||||
* 音频波形可视化组件
|
||||
* 使用 SVG 绘制实时波形
|
||||
*/
|
||||
export function AudioWaveform({
|
||||
waveform,
|
||||
color = "var(--cn-accent, #3b82f6)",
|
||||
height = 48,
|
||||
width = 200,
|
||||
animated = true,
|
||||
}: AudioWaveformProps) {
|
||||
// 如果没有波形数据,显示占位波形
|
||||
const displayWaveform = useMemo(() => {
|
||||
if (waveform.length === 0) {
|
||||
// 生成静态占位波形
|
||||
return Array.from({ length: 32 }, (_, i) => {
|
||||
const x = i / 31;
|
||||
return 0.3 + 0.2 * Math.sin(x * Math.PI * 2);
|
||||
});
|
||||
}
|
||||
return waveform;
|
||||
}, [waveform]);
|
||||
|
||||
const barWidth = width / displayWaveform.length;
|
||||
const gap = Math.max(1, barWidth * 0.2);
|
||||
const actualBarWidth = barWidth - gap;
|
||||
|
||||
return (
|
||||
<svg
|
||||
width={width}
|
||||
height={height}
|
||||
viewBox={`0 0 ${width} ${height}`}
|
||||
className={animated ? "animate-pulse" : ""}
|
||||
style={{ overflow: "visible" }}
|
||||
>
|
||||
{displayWaveform.map((value, index) => {
|
||||
const barHeight = Math.max(2, value * height * 0.8);
|
||||
const x = index * barWidth + gap / 2;
|
||||
const y = (height - barHeight) / 2;
|
||||
return (
|
||||
<rect
|
||||
key={index}
|
||||
x={x}
|
||||
y={y}
|
||||
width={actualBarWidth}
|
||||
height={barHeight}
|
||||
fill={color}
|
||||
rx={actualBarWidth / 2}
|
||||
opacity={0.6 + value * 0.4}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user