h5实现音频录制功能

143 阅读1分钟
<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>按住录音 Demo</title>
    <style>
        #recordButton {
            width: 80px;
            height: 80px;
            background-color: #f44336;
            border-radius: 50%;
            border: none;
            color: white;
            font-size: 16px;
            cursor: pointer;
            margin: 20px;
            outline: none;
        }

        #recordButton:active {
            background-color: #d32f2f;
        }

        #status {
            margin: 10px;
            font-weight: bold;
        }

        .recording {
            color: red;
            animation: pulse 1s infinite;
        }

        @keyframes pulse {
            0% {
                opacity: 1;
            }

            50% {
                opacity: 0.5;
            }

            100% {
                opacity: 1;
            }
        }

        audio {
            display: block;
            margin: 10px 0;
        }
    </style>
</head>

<body>
    <h1>语音录制 Demo</h1>
    <button id="recordButton">按住录音</button>
    <div id="status">准备就绪</div>
    <div id="recordingsList"></div>

    <script>
        // 核心变量
        let mediaRecorder;
        let audioChunks = [];
        const recordButton = document.getElementById('recordButton');
        const statusDisplay = document.getElementById('status');
        const recordingsList = document.getElementById('recordingsList');

        // 1. 初始化录音功能
        async function initRecorder() {
            try {
                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.onstop = () => {
                    const audioBlob = new Blob(audioChunks, { type: 'audio/webm' });
                    createAudioElement(audioBlob);
                    audioChunks = [];
                    statusDisplay.textContent = "录音完成";
                };

                statusDisplay.textContent = "麦克风已启用";
            } catch (error) {
                statusDisplay.textContent = "麦克风权限被拒绝或设备不支持";
                console.error("录音初始化失败:", error);
            }
        }

        // 2. 创建播放控件
        function createAudioElement(blob) {
            const audioURL = URL.createObjectURL(blob);
            const audioElement = document.createElement('audio');
            const downloadLink = document.createElement('a');

            audioElement.controls = true;
            audioElement.src = audioURL;

            downloadLink.href = audioURL;
            downloadLink.download = `recording-${new Date().toISOString()}.webm`;
            downloadLink.textContent = "下载录音";

            const container = document.createElement('div');
            container.appendChild(audioElement);
            container.appendChild(downloadLink);
            container.appendChild(document.createElement('hr'));

            recordingsList.prepend(container);
        }

        // 3. 按钮事件绑定
        recordButton.addEventListener('mousedown', async () => {
            console.log('mouse');
            if (!mediaRecorder) await initRecorder();
            if (mediaRecorder.state === 'inactive') {
                mediaRecorder.start();
                statusDisplay.textContent = "录音中...";
                statusDisplay.classList.add('recording');
            }
        });

        recordButton.addEventListener('mouseup', () => {
            if (mediaRecorder && mediaRecorder.state === 'recording') {
                mediaRecorder.stop();
                statusDisplay.classList.remove('recording');
            }
        });

        // 移动端触摸事件支持
        recordButton.addEventListener('touchstart', async (e) => {
            console.log('touch');
            e.preventDefault();
            if (!mediaRecorder) await initRecorder();
            if (mediaRecorder.state === 'inactive') {
                mediaRecorder.start();
                statusDisplay.textContent = "录音中...";
                statusDisplay.classList.add('recording');
            }
        });

        recordButton.addEventListener('touchend', (e) => {
            e.preventDefault();
            if (mediaRecorder && mediaRecorder.state === 'recording') {
                mediaRecorder.stop();
                statusDisplay.classList.remove('recording');
            }
        });
    </script>
</body>

</html>