最近正在实现“视频配音练习”功能,用户可以观看视频片段,逐句录音配音,系统再根据中文字幕对用户发音进行评分。过程中有许多收获,以下是记录。
🌟 功能简介
主要功能包括:
- 视频播放与字幕同步显示
- 逐句配音录音
- 上传音频并进行评分(使用后端接口)
- 录音回放与评分展示
界面简洁,功能明确,适合用户逐句练习中文发音。
📦 技术实现要点
1. 视频播放与字幕同步高亮
通过 <video>
标签播放视频,并用 onTimeUpdate
监听视频的播放进度,利用 currentTime
匹配字幕时间段,动态高亮当前句子:
const time = videoRef.current.currentTime;
const idx = subtitles.findIndex(
(s) => time >= s.start && time <= s.end
);
setCurrentIdx(idx);
2. 录音功能:MediaRecorder API
录音的关键在于 navigator.mediaDevices.getUserMedia()
和 MediaRecorder
,用户点击“配音”按钮即开始录音,“停止”按钮停止录音后,将音频转为 blob 并生成播放链接:
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
const mediaRecorder = new MediaRecorder(stream);
mediaRecorder.ondataavailable = (e) => {
audioChunks.current.push(e.data);
};
3. 上传音频并获取评分
录音结束后,我使用 FileReader
将音频转换为 Base64,并 POST 到 /api/dubbing
接口,服务器接收后进行分析并返回一个评分:
const base64 = (reader.result as string).split(",")[1];
const res = await fetch("/api/dubbing", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ audio: base64, text: subtitles[currentIdx!].en }),
});
评分结果动态展示在对应字幕下方。
💡 遇到的问题与解决
🎤 录音权限管理
首次调试时浏览器未弹出权限请求,导致录音失败。解决方式是确保 getUserMedia 被调用后有相应的用户交互,比如按钮触发。
🔁 状态管理混乱
在多句字幕场景中,需要管理每一句的录音状态、评分、播放链接。我简化逻辑为“当前句子录音状态”,避免一页多个录音状态混乱。
🌐 文件上传与 Base64 转换
Base64 编码上传虽简单,但不适合大文件。后续可以优化为 FormData
方式上传 Blob,降低编码开销。
✅ 收获与反思
- 对媒体 API 的理解更深入:亲手用
MediaRecorder
实现录音让我真正理解了浏览器端音视频处理的机制。 - React 状态管理经验增强:多个动态状态(播放进度、录音状态、评分、音频播放)管理让我更加熟练使用
useState
和useRef
。 - 用户体验更敏感:为用户提供及时反馈(如“评分中…”、“录音回放”)是提升产品体验的重要一环。
- 后端协作意识提升:配音评分功能需要后端接口支持,也让我意识到 API 设计和前后端数据结构约定的重要性。
📌 后续优化方向
- 支持逐句打分并保存历史成绩
- 增加字幕点击跳转视频的功能
- 支持自动切换下一句录音,提升效率
- 增加录音进度条或音量波形,增强交互感
总之,这次开发视频配音练习功能不仅让我提升了技术能力,也更加理解了如何为用户构建一个有反馈、有价值的语言学习工具。