WebRtc实时音波

摘要:

最近在做音视频相关业务,用的到了webRtc技术,掌握这些方法可以结合业务做,麦克风检测、录制音频,都是可以的;基本操作和其它方法都写好在methods中了;

全局变量
typescript 复制代码
// 后续会创建AnalyserNode对象
let analyser: any = null;
// 后续赋值canvas标签对象
let canvas: any = null;
// canvas 2d对象
let canvasCtx: any = null;
let audioSteam: any = { // 获取音视频MediaStream对象
    current: null
}
HTML
html 复制代码
<div>
    // 绘制音波
    <canvas id="devDetectionMicroCanvas" className={style.audio_canvas}></canvas>
    // 实时播放
    <audio id="devDetectionMicroRef" autoPlay></audio>
</div>
获取音视频流
typescript 复制代码
// 使用getUserMedia API获取音频流。
navigator.mediaDevices.getUserMedia({
    audio: true
}).then(stream => {
    /* MediaStream赋值到全局对象,后续使用 */
    audioSteam.current = stream;
    /* 获取当前采集设备名称 */
    methods.handleStreamGetMicroName();
    /* 把媒体流赋值给audio标签进行试试播放 */
    methods.handleAudioPlay();
    /* 开始准备制作试试音波 */
    methods.handleCanvasAudioContext();
})
.catch(error => {
    let errorMessage = error + '';
    if (errorMessage.includes('Permission denied')) {
        errorMessage = '请开启麦克风权限';
    } else if (errorMessage.includes('Requested device not found')) {
        errorMessage = '请检测麦克风是否插入';
    };
    console.log('error', errorMessage)
});
其它方法
typescript 复制代码
const methods = {
    // 处理canvas和audioContext
    handleCanvasAudioContext() {
         // 1. 使用AudioContext API创建一个AudioContext对象,并将音频流添加到它上面
        const audioContext = new AudioContext();
        const source = audioContext.createMediaStreamSource(stream);
        // 2. 创建AnalyserNode对象,并将其连接到source节点。
        analyser = audioContext.createAnalyser();
        source.connect(analyser);
        // 3. 获取实时音频数据并将其转换为可视化数据。例如,可以使用getByteTimeDomainData()方法获取时域数据,并将其转换为音波。
        canvas = document.getElementById("devDetectionMicroCanvas");
        canvasCtx = canvas.getContext("2d");
        // 4.启动波纹动画
        methods.drawWaveform();
    },
    // 波纹动画
    drawWaveform() {
        const stream = audioSteam.current;
        // 获取时域数据
        const dataArray = new Uint8Array(analyser.fftSize);
        analyser.getByteTimeDomainData(dataArray);

        // 绘制音波
        canvasCtx.clearRect(0, 0, canvas.width, canvas.height);
        canvasCtx.lineWidth = 2;
        canvasCtx.strokeStyle = "rgb(69, 255, 56)";
        canvasCtx.beginPath();
        const sliceWidth = canvas.width * 1.0 / analyser.fftSize;
        let x = 0;
        for(let i = 0; i < analyser.fftSize; i++) {
            const v = dataArray[i] / 128.0;
            const y = v * canvas.height / 2;
            if(i === 0) {
                canvasCtx.moveTo(x, y);
            } else {
                canvasCtx.lineTo(x, y);
            }
            x += sliceWidth;
        }
        canvasCtx.stroke();
        requestAnimationFrame(methods.drawWaveform);
    },
    // 获取采集设备名称
    handleStreamGetMicroName(){
        if (audioSteam.current) {
            const audioTrack = audioSteam.current.getAudioTracks()[0];
            // audioTrack.label;
            console.log('当前采集设备名称', audioTrack.label);
        }
    },
    // 处理audio播放
    handleAudioPlay() {
        const stream = audioSteam.current;
        const elm: HTMLVideoElement | any = document.getElementById('devDetectionMicroRef');
        if (elm) {
            elm.srcObject = stream;
        }
    },
    // 停止麦克采集
    stopAudioSteam() {
        if (audioSteam.current) {
            audioSteam.current.getTracks().forEach((sender: any) => {
                sender.stop();
            });
        }
    },
}
相关推荐
程序员黑豆21 小时前
Java包装类:基本类型与对象的桥梁
java·前端·ai编程
bugcome_com1 天前
JWT 知识小课堂:从入门到精通,一文吃透 JSON Web Token
前端·json
To_OC1 天前
写了三天 Next.js,我的 React 世界观被拆了又装回去
前端·全栈·next.js
独泪了无痕1 天前
viewer.js 安装与配置指南:实现图片预览功能
前端·vue.js
起床学FPGA1 天前
AI回答问题之后,会自动跳到最下面的问题
开发语言·javascript·ecmascript
Fluxart.ai1 天前
电商商品图审核怎么自动化?规则引擎、人工复核与发布门禁
java·前端·自动化
why技术1 天前
AI 写的文章,可能都带着手敲一遍都去不掉的“隐形水印”。
前端·人工智能·后端
愚公搬代码1 天前
【愚公系列】《Android应用案例开发大全》016-LBS类应用掌上杭州(辅助工具类的开发)
android·前端
CodeSheep1 天前
又一个华为天才少年,离职了!
前端·后端·程序员
kyriewen1 天前
面试官说"打开你的AI工具"——我才发现,他考的根本不是写代码
前端·人工智能·面试