导读:本期聚焦于小伙伴创作的《使用JavaScript和ffmpeg.wasm实现浏览器录音音频切分为5秒WAV片段》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《使用JavaScript和ffmpeg.wasm实现浏览器录音音频切分为5秒WAV片段》有用,将其分享出去将是对创作者最好的鼓励。

使用 JavaScript 和 ffmpeg.wasm 将录音 Blob 流切分并转换为多个 5 秒的 WAV 文件

引言

在现代Web应用中,音频处理变得越来越常见。本文将介绍如何使用JavaScript和ffmpeg.wasm库来处理录音数据,将其切分为多个5秒的WAV文件。

准备工作

首先,我们需要在项目中引入ffmpeg.wasm。可以通过CDN方式引入:

<script src="https://unpkg.com/@ffmpeg/ffmpeg@latest/dist/ffmpeg.min.js"></script>

实现步骤

1. 初始化FFmpeg

首先需要加载FFmpeg核心:

const { createFFmpeg, fetchFile } = FFmpeg;
const ffmpeg = createFFmpeg({ log: true });

// 加载FFmpeg核心
await ffmpeg.load();

2. 录音功能实现

使用MediaRecorder API进行录音:

let mediaRecorder;
let audioChunks = [];

// 开始录音
async function startRecording() {
    const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
    mediaRecorder = new MediaRecorder(stream);
    
    mediaRecorder.ondataavailable = (event) => {
        if (event.data.size > 0) {
            audioChunks.push(event.data);
        }
    };
    
    mediaRecorder.start(5000); // 每5秒触发一次dataavailable事件
}

// 停止录音
function stopRecording() {
    return new Promise((resolve) => {
        mediaRecorder.onstop = () => {
            const audioBlob = new Blob(audioChunks, { type: 'audio/webm' });
            resolve(audioBlob);
        };
        mediaRecorder.stop();
    });
}

3. 音频处理和切分

使用ffmpeg.wasm处理音频并切分为5秒片段:

async function splitAudioIntoChunks(audioBlob) {
    // 将Blob写入FFmpeg文件系统
    ffmpeg.FS('writeFile', 'input.webm', await fetchFile(audioBlob));
    
    // 使用FFmpeg命令切分音频
    // -i input.webm: 输入文件
    // -f segment: 使用分段器
    // -segment_time 5: 每段5秒
    // -c copy: 直接复制编码,不重新编码
    // output_%03d.wav: 输出文件名模式
    await ffmpeg.run(
        '-i', 'input.webm',
        '-f', 'segment',
        '-segment_time', '5',
        '-c', 'copy',
        'output_%03d.wav'
    );
    
    // 读取所有生成的文件
    const chunks = [];
    let i = 0;
    while (true) {
        try {
            const data = ffmpeg.FS('readFile', `output_${String(i).padStart(3, '0')}.wav`);
            chunks.push(new Blob([data.buffer], { type: 'audio/wav' }));
            i++;
        } catch (error) {
            break;
        }
    }
    
    return chunks;
}

4. 完整的使用示例

整合上述功能的完整示例:

class AudioSplitter {
    constructor() {
        this.ffmpeg = createFFmpeg({ log: true });
        this.audioChunks = [];
    }
    
    async initialize() {
        await this.ffmpeg.load();
    }
    
    async startRecording() {
        const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
        this.mediaRecorder = new MediaRecorder(stream);
        
        this.mediaRecorder.ondataavailable = (event) => {
            if (event.data.size > 0) {
                this.audioChunks.push(event.data);
            }
        };
        
        this.mediaRecorder.start(5000);
    }
    
    async stopAndSplitRecording() {
        return new Promise((resolve) => {
            this.mediaRecorder.onstop = async () => {
                const audioBlob = new Blob(this.audioChunks, { type: 'audio/webm' });
                const chunks = await this.splitAudioIntoChunks(audioBlob);
                this.audioChunks = []; // 清空数组
                resolve(chunks);
            };
            this.mediaRecorder.stop();
        });
    }
    
    async splitAudioIntoChunks(audioBlob) {
        this.ffmpeg.FS('writeFile', 'input.webm', await fetchFile(audioBlob));
        
        await this.ffmpeg.run(
            '-i', 'input.webm',
            '-f', 'segment',
            '-segment_time', '5',
            '-c', 'copy',
            'output_%03d.wav'
        );
        
        const chunks = [];
        let i = 0;
        while (true) {
            try {
                const data = this.ffmpeg.FS('readFile', `output_${String(i).padStart(3, '0')}.wav`);
                chunks.push(new Blob([data.buffer], { type: 'audio/wav' }));
                i++;
            } catch (error) {
                break;
            }
        }
        
        return chunks;
    }
}

// 使用示例
const splitter = new AudioSplitter();
await splitter.initialize();

// 开始录音
await splitter.startRecording();

// 10秒后停止并获取切分的音频块
setTimeout(async () => {
    const chunks = await splitter.stopAndSplitRecording();
    console.log(`生成了 ${chunks.length} 个音频片段`);
    
    // 可以在这里处理每个音频片段,比如下载或上传
    chunks.forEach((chunk, index) => {
        const url = URL.createObjectURL(chunk);
        const a = document.createElement('a');
        a.href = url;
        a.download = `audio_chunk_${index + 1}.wav`;
        a.click();
        URL.revokeObjectURL(url);
    });
}, 10000);

注意事项

  • ffmpeg.wasm文件较大,首次加载可能需要较长时间
  • 浏览器兼容性需要考虑,特别是MediaRecorder API的支持情况
  • 录音权限需要用户授权
  • 可以根据需要调整切分的时间间隔
  • 在生产环境中,建议添加适当的错误处理和用户反馈

总结

通过结合JavaScript的MediaRecorder API和ffmpeg.wasm,我们可以轻松地在浏览器中实现音频录制和切分功能。这种方法无需服务器端处理,完全在客户端完成,保护了用户隐私并减少了服务器负载。

音频切分 ffmpeg.wasm JavaScript 录音处理 WAV转换

免责声明:已尽一切努力确保本网站所含信息的准确性。网站部分内容来源于网络或由用户自行发表,内容观点不代表本站立场。本站是个人网站免费分享,内容仅供个人学习、研究或参考使用,如内容中引用了第三方作品,其版权归原作者所有。若内容触犯了您的权益,请联系我们进行处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。前端、网络、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握网站开发与运维所需的核心技术栈。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端逻辑,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。