Как сохранить поток MediaRecorder в файл OGG в PHP? Включая метаданные

Я предоставляю своим пользователям аудиозапись в браузере, используя Javascript:

navigator.mediaDevices.getUserMedia(media.gUM).then(_stream => 
{
    stream = _stream;
    recorder = new MediaRecorder(stream);

    recorder.ondataavailable = e => 
    {
        // push data to chunks
        chunks.push(e.data);

        // recording has been stopped
        if(recorder.state == 'inactive') 
        {
            blob = new Blob(chunks, {type: media.type });
            blob_url = URL.createObjectURL(blob);
            
            $('.rec_result_audio').attr({
                'src': blob_url
            });
            
            // send data to server
            // append file to object to be sent
            var filedata = new FormData();
            filedata.append('recfile', blob, blob_url);

            // send by AJAX/POST
        }
    };
}

В PHP я получаю и сохраняю поток следующим образом:

if(!empty($_FILES)) 
{
    $filename = $_FILES['recfile']['name'];
    $file_locationtmp = $_FILES['recfile']['tmp_name'];
    $filetype = $_FILES['recfile']['type'];
    $filesize_bytes = $_FILES['recfile']['size'];
    
    // add file extension to string
    $_FILES['recfile']['name'] = $_FILES['recfile']['name'].'.ogg';

    // save to filesystem
}

Теперь файл OGG (webm с кодеком opus) хранится на сервере. Однако все метаданные отсутствуют. Таким образом, панель воспроизведения не работает. См. Здесь для получения дополнительной информации: HTML5 Audio - Progressbar / Playbar не работает для аудиофайла OGG / Проблема с 206 частичным содержимым

метаданные ogg пустые

Length отсутствует. Также Bit rate, Channels и Audio sample rate.

Очевидно, что прямого сохранения в файловую систему с помощью PHP недостаточно.

Чего не хватает в коде PHP, чтобы файл позже распознавался как файл OGG?

Нужно ли мне добавлять метаданные, и если да, то как?


person Avatar    schedule 11.04.2021    source источник
comment
По теме: stackoverflow.com/questions/63640361/   -  person chiliNUT    schedule 13.04.2021
comment
Спасибо за подсказку. Эта библиотека Javascript добавит 21 КБ к моему основному файлу JS. Это много. Есть ли способ сделать это напрямую с помощью сервера PHP?   -  person Avatar    schedule 13.04.2021
comment
Я только что наткнулся на github.com/JamesHeinrich/getID3 и сообщу, поможет ли это решить проблему. .   -  person Avatar    schedule 13.04.2021
comment
О, хороший звонок, делаю это на php   -  person chiliNUT    schedule 13.04.2021
comment
Похоже, запись метаданных в этот формат webm / audio не поддерживается. ???? github.com/JamesHeinrich/getID3/issues/307   -  person Avatar    schedule 15.04.2021


Ответы (4)


Мне, вероятно, не хватает чего-то очевидного, но - не следует ли вам указывать, что вы хотите поток Javascript должен быть OGG / Vorbis?

recorder = new MediaRecorder(stream, { mimeType: "audio/ogg; codecs=vorbis" });

Могу ошибиться, но полученный файл:

Теперь файл OGG (webm с кодеком opus) хранится на сервере. Однако все метаданные отсутствуют.

на самом деле не является файлом OGG - это файл WEBM. Таким образом, присвоение ему расширения .ogg вместо .webm, как вы это делаете, вероятно, сбивает систему с толку, и поэтому файл кажется нечитаемым и в нем отсутствуют метаданные.

person LSerni    schedule 30.04.2021
comment
В Chrome я получаю Uncaught (в обещании) DOMException: не удалось создать «MediaRecorder»: не удалось инициализировать собственный MediaRecorder, указанный тип (audio / ogg; codecs = vorbis) не поддерживается. - person Avatar; 02.05.2021
comment
Что ж, боюсь, тогда это ваш ответ. Вам необходимо загрузить поток в любом формате, поддерживаемом браузером, а затем преобразовать его в формат OGG (если вы не сохраните его как .webm. Что произойдет, если вы используете расширение файла .webm?). - person LSerni; 02.05.2021

Самое простое решение - загрузить уже скомпилированный двоичный файл ffmpeg и указать на него свой скрипт. На странице загрузки FFmpeg перейдите в раздел «Получить пакеты», чтобы найти ссылки на последние статические сборки для Linux, Windows и macOS.

Вы можете использовать shell_exec (), как показано в FFmpeg Wiki: PHP, и указать полный путь к загруженному двоичному файлу.

person javad shariaty    schedule 13.04.2021
comment
Не могли бы вы добавить в свой ответ необходимый PHP-код? Я никогда раньше не использовал ffmpeg. - person Avatar; 15.04.2021
comment
ffmpeg -i input.mp4 -codec: v libtheora -qscale: v 3 -codec: a libvorbis \ -qscale: a 3 -f ogv output.ogv - person javad shariaty; 15.04.2021
comment
Но я пытаюсь найти решение PHP, которое также работает на серверах, которые не поставляются с ffmpeg. - person Avatar; 25.04.2021

Другой вариант - написать с помощью оболочки ogg://, которая знает о метаданные.
Пакет PECL libvorbis выглядит немного устаревшим, но в конечном итоге он все равно будет построен для PHP 7.

person Martin Zeitler    schedule 28.04.2021

На данный момент я решил проблему только с использованием ffmpeg для преобразования файлового сервера, но не напрямую в PHP.

  1. Установите ffmpeg на свой сервер с sudo apt install ffmpeg

  2. Используйте ffmpeg в своем PHP-скрипте:

// physical path to uploaded file
$filelocationtmp = $_FILES['recfile']['tmp_name'];

// call ffmpeg script to convert file
shell_exec("ffmpeg -y -i ".$filelocationtmp." -c:a libvorbis -vn -b:a 48k ".$filelocationtmp.".oga");

// rename oga file to original file (overrides original)
shell_exec("mv ".$filelocationtmp.".oga ".$filelocationtmp);

Примечание: ffmpeg не может читать входной файл и записывать выходной файл одновременно. Вот почему необходима вторая командная строка.



⚠️ Это не чисто PHP-решение. Так что вопрос остается открытым.

person Avatar    schedule 28.04.2021