Почему отваливается коннект websocket в связке JS-PHP при передаче звука с микрофона?
Пытаюсь посмотреть возможности передачи потоковых данных в режиме онлайн через вебсокеты. Для начала решил поэксперементировать только со звуком, т.е. реализовать подобие голосового чата. Т.к. наиболее близко знаком с PHP, на пощупать реализую сервер на этом языке с помощью Workerman. Суть проблемы: есть простейший код клиента на JS, который берёт поток с микрофона, режет его рекордером и отправляет серверу.
var socket = new WebSocket('ws://10.0.0.5:27801/');
navigator.mediaDevices.getUserMedia({
audio: true
})
.then(function(stream) {
var $audio = document.getElementById("audio");
var mediarecorder = new MediaRecorder(stream, {mimeType: "audio/webm; codecs=\"opus\""});
// send
mediarecorder.ondataavailable = function(e) {
if (e.data && e.data.size > 0) {
socket.send(e.data);
}
}
mediarecorder.start(1000);
});
И есть простейший сервер на PHP, который просто отправляет полученные данные обратно.
<?php
include_once(__DIR__."/Workerman/Autoloader.php");
use Workerman\Lib\Timer;
use Workerman\Worker;
$worker = new Worker("websocket://0.0.0.0:27801");
$worker->onConnect = function($c){
echo "Connected\n";
};
$worker->onMessage = function($c, $data){
$c->send($data);
};
Worker::runAll();
Так вот если таким подходом отправлять текст, то всё ок. Но в описаной выше ситуации коннект на js просто отваливается при передаче данных с ошибкой в строке коннекта
WebSocket connection to 'ws://10.0.0.5:27801/' failed: Could not decode a text frame as UTF-8.
Нагуглить решение не удалось, менять тип коннекта на сервере пробовал. Что в данной ситуации пошло не так?
Ответы (1 шт):
Посмотрел ваш пример. Проблема здесь возникает из-за типа фрейма у вебсокета. Workerman по умолчанию посылает текстовый фрейм. JS видим что фрейм текстовый и ждёт что все символы будут в UTF-8. Не знаю как его правильно поменять в Workerman. Сходу не нашёл в документации. Получилось сделать так:
$worker->onMessage = function($c, $data){
$c->websocketType = \Workerman\Protocols\Websocket::BINARY_TYPE_ARRAYBUFFER;
$c->send($data);
};
Подсмотрел параметр соответственно в Websocket::encode(), через который пропускаются отправляемые данные. О чём написано в документации.