+
80
-

js在浏览器中如何使用MediaStream与MediaRecorder实现声音音频多轨道混流?

js在浏览器中如何使用MediaStream与MediaRecorder实现声音音频多轨道混流?


网友回复

+
25
-

这个可以实现,多音轨合并混流音频,可拖拽时间

800_auto

完整代码

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>HTML5 音频编辑器</title>
    <style>
        body { font-family: sans-serif; margin: 20px; background-color: #f4f4f4; color: #333; }
        .controls button { margin: 5px; padding: 10px 15px; background-color: #007bff; color: white; border: none; cursor: pointer; border-radius: 4px; }
        .controls button:hover { background-color: #0056b3; }
        .tracks-container {
            margin-top: 20px;
            border: 1px solid #ccc;
            padding: 10px;
            background-color: #fff;
            position: relative; /* For absolute positioning of ruler */
            overflow-x: auto; /* Allow horizontal scrolling for long timelines */
        }
        .timeline-ruler {
            height: 20px;
            background-color: #e0e0e0;
            position: sticky; /* Make ruler sticky */
            top: 0;
            z-index: 10;
            display: flex;
        }
        .ruler-mark {
            min-width: 50px; /* Corresponds to 1 second if pixelsPerSecond is 50 */
            border-left: 1px solid #aaa;
            font-size: 10px;
            text-align: right;
            padding-right: 2px;
            box-sizing: border-box;
        }
        .track {
            border: 1px dashed #ddd;
            margin-bottom: 10px;
            min-height: 60px; /* Min height for dropping files */
            position: relative; /* Crucial for absolute positioning of clips */
            background-color: #f9f9f9;
            padding: 5px 0; /* Add some padding for clips */
        }
        .track-header {
            font-size: 0.9em;
            color: #555;
            padding: 2px 5px;
            background-color: #eee;
            display: flex;
            justify-content: space-between;
            align-items: center;
        }
        .track-header input[type="file"] { display: none; }
        .audio-clip {
            position: absolute;
            height: 50px;
            background-color: lightcoral;
            border: 1px solid darkred;
            border-radius: 3px;
            cursor: move;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 0.8em;
            color: white;
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;
            box-sizing: border-box;
            padding: 0 5px;
        }
        .drop-zone-active {
            border: 2px dashed dodgerblue !important;
            background-color: #e6f7ff !important;
        }
        #loading-indicator {
            display: none;
            position: fixed;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            padding: 20px;
            background: rgba(0,0,0,0.7);
            color: white;
            border-radius: 5px;
            z-index: 1000;
        }
    </style>
</head>
<body>
    <h1>简易音频混音器</h1>

    <div class="controls">
        <button id="addTrackBtn">添加音轨</button>
        <button id="mergeAndDownloadBtn">合并并下载 (WAV)</button>
    </div>

    <div class="tracks-container">
        <div class="timeline-ruler" id="timelineRuler">
            <!-- Ruler marks will be generated by JS -->
        </div>
        <div id="tracks">
            <!-- Audio tracks will be added here -->
        </div>
    </div>

    <div id="loading-indicator">处理中,请稍候...</div>

    <script>
       document.addEventListener('DOMContentLoaded', () => {
    const addTrackBtn = document.getElementById('addTrackBtn');
    const mergeAndDownloadBtn = document.getElementById('mergeAndDownloadBtn');
    const tracksContainer = document.getElementById('tracks');
    const timelineRuler = document.getElementById('timelineRuler');
    const loadingIndicator = document.getElementById('loading-indicator');

    let audioContext;
    let tracksData = []; // Array to store data for each track and its clips
    let trackIdCounter = 0;
    let clipIdCounter = 0;
    const PIXELS_PER_SECOND = 50; // 50 pixels represent 1 second
    const MAX_TIMELINE_SECONDS = 180; // Max length of timeline ruler

    // Initialize AudioContext
    function initAudioContext() {
        if (!audioContext) {
            audioContext = new (window.AudioContext || window.webkitAudioContext)();
        }
        if (!audioContext) {
            alert("浏览器不支持 Web Audio API");
            return false;
        }
        return true;
    }

    // Generate timeline ruler
    function generateTimelineRuler() {
        timelineRuler.innerHTML = ''; // Clear existing marks
        for (let i = 0; i < MAX_TIMELINE_SECONDS; i++) {
            const mark = document.createElement('div');
            mark.classList.add('ruler-mark');
            mark.style.minWidth = `${PIXELS_PER_SECOND}px`;
            mark.textContent = `${i}s`;
            timelineRuler.appendChild(mark);
        }
        // Ensure the tracks container is wide enough
        tracksContainer.style.minWidth = `${MAX_TIMELINE_SECONDS * PIXELS_PER_SECOND}px`;
    }


    // Add a new track
    addTrackBtn.addEventListener('click', () => {
        if (!initAudioContext()) return;
        createTrackElement();
    });

    function createTrackElement() {
        const trackId = `track-${trackIdCounter++}`;
        const trackDiv = document.createElement('div');
        trackDiv.classList.add('trac...

点击查看剩余70%

我知道答案,我要回答