Как из этого скрипта сделать скрипт с сохранением нескольких записей?

Нашёл в интернете такой скрипт для записи голоса:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Подай Голос</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            display: flex;
            flex-direction: column;
            align-items: center;
            margin-top: 50px;
        }
        button {
            margin: 5px;
            padding: 10px 20px;
            font-size: 16px;
        }
    </style>
</head>
<body>

<h1>Диктофон</h1>
<input type="text" id="file-name" placeholder="Enter file name" />
<button id="start-btn">Записать</button>
<button id="stop-btn" disabled>Остановить Запись</button>
<audio id="audio-playback" controls style="display:none;"></audio>

<script>
    let mediaRecorder;
    let chunks = [];

    const startButton = document.getElementById('start-btn');
    const stopButton = document.getElementById('stop-btn');
    const audioPlayback = document.getElementById('audio-playback');
    const fileNameInput = document.getElementById('file-name');

    startButton.onclick = async () => {
        const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
        mediaRecorder = new MediaRecorder(stream);

        mediaRecorder.start();
        startButton.disabled = true;
        stopButton.disabled = false;

        mediaRecorder.ondataavailable = event => {
            chunks.push(event.data);
        };

        mediaRecorder.onstop = async () => {
            const audioBlob = new Blob(chunks, { type: 'audio/wav' });
            chunks = []; // Clear chunks for next recording

            const fileName = fileNameInput.value || `recording_${Date.now()}`; // Default naming if user does not provide
            const formData = new FormData();
            formData.append('audio', audioBlob, fileName + '.wav'); // Append the blob and the name

            // Send the blob to the server
            await fetch('upload.php', {
                method: 'POST',
                body: formData,
            });

            // Optional: play back the recorded audio
            const audioUrl = URL.createObjectURL(audioBlob);
            audioPlayback.src = audioUrl;
            audioPlayback.style.display = 'block';
            audioPlayback.play();

            startButton.disabled = false;
            stopButton.disabled = true;
            fileNameInput.value = ''; // Clear the input after recording
        };
    };

    stopButton.onclick = () => {
        mediaRecorder.stop();
    };
</script>

</body>
</html>
</code>

Опытным путём выяснил, что в таком варианте он сохраняет всего одну запись за сессию, а при повторной записи предыдущая сбрасывается. Как можно изменить этот скрипт, чтобы записи накапливались?


Ответы (1 шт):

Автор решения: Lagutkin Denis

Ниже пример, когда записи сохраняются в памяти и не отправляются на сервер. Если отправка необходима, можете вернуть fetch из вашего примера. Хочу обратить внимание, что переменная chunks в глобальном пространстве не нужна в моем примере, ссылка на байтовую последовательность сохраняется в функции onClick, но для совместимости с вашим примером оставил.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Подай Голос</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            display: flex;
            flex-direction: column;
            align-items: center;
            margin-top: 50px;
        }
        button {
            margin: 5px;
            padding: 10px 20px;
            font-size: 16px;
        }
    </style>
</head>
<body>

<h1>Диктофон</h1>
<input type="text" id="file-name" placeholder="Enter file name" />
<button id="start-btn">Записать</button>
<button id="stop-btn" disabled>Остановить Запись</button>
<div id="playlist"></div>
<audio id="audio-playback" controls style="display:none;"></audio>

<script>
    let mediaRecorder;
    let chunks = {};

    const startButton = document.getElementById('start-btn');
    const stopButton = document.getElementById('stop-btn');
    const audioPlayback = document.getElementById('audio-playback');
    const fileNameInput = document.getElementById('file-name');

    startButton.onclick = async () => {
        const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
        mediaRecorder = new MediaRecorder(stream);

        mediaRecorder.start();
        startButton.disabled = true;
        stopButton.disabled = false;

        const fileName = fileNameInput.value || `recording_${Date.now()}`;
        const currentChunks = chunks[fileName] = []

        mediaRecorder.ondataavailable = event => {
            currentChunks.push(event.data);
        };

        mediaRecorder.onstop = async () => {

            const newRecord = document.createElement('div');
            newRecord.onclick = () => {
                const audioBlob = new Blob(currentChunks, { type: 'audio/wav' });
                const audioUrl = URL.createObjectURL(audioBlob);
                audioPlayback.src = audioUrl;
                audioPlayback.style.display = 'block';
                audioPlayback.play();
            };
            newRecord.textContent = fileName;
            newRecord.style.cursor = 'pointer';

            document.getElementById('playlist').appendChild(newRecord);

            startButton.disabled = false;
            stopButton.disabled = true;
            fileNameInput.value = ''; // Clear the input after recording
        };
    };

    stopButton.onclick = () => {
        mediaRecorder.stop();
    };
</script>

</body>
</html>

→ Ссылка