Я использую Ratchet для подключения к веб-сокетам IBM Watson, и кажется, что он всегда работает нормально для небольших файлов (я тестировал до 66-минутного файла MP3 размером 23 МБ), но он всегда терпит неудачу для большие файлы (например, 2 часа 56 МБ mp3).
Это мой журнал:
[2019-03-17 21:43:23] local.DEBUG: \Ratchet\Client\connect bf4e38983775f6e53b392666138b5a3a50e9c9c8
[2019-03-17 21:43:24] local.DEBUG: startWatsonStream options = {"content-type":"audio\/mpeg","timestamps":true,"speaker_labels":true,"smart_formatting":true,"inactivity_timeout":-1,"interim_results":false,"max_alternatives":1,"word_confidence":false,"action":"start"}
[2019-03-17 21:43:24] local.DEBUG: Split audio into this many frames: 570222
[2019-03-17 21:43:42] local.DEBUG: send action stop
[2019-03-17 21:43:42] local.DEBUG: Received: {
"state": "listening"
}
[2019-03-17 21:43:42] local.DEBUG: Received first 'listening' message.
[2019-03-17 22:56:31] local.DEBUG: Connection closed (1006 - Underlying connection closed)
Обратите внимание на 1 ч 13 м между получением первого «прослушивающего» сообщения и последующим закрытием соединения с ошибкой.
Ватсон говорит: «1006 указывает, что соединение закрыто ненормально».
https://tools.ietf.org/html/rfc6455 говорит:
1006 является зарезервированным значением и НЕ ДОЛЖНО быть установлено конечным пунктом как код состояния в кадре управления Close. Он предназначен для использования в приложениях, ожидающих, что код состояния указывает на ненормальное закрытие соединения, например, без отправки или получения кадра управления Close.
Какую часть моего кода я могу настроить, чтобы он мог обрабатывать более длинные mp3-файлы, не выдавая ошибку 1006?
\Ratchet\Client\connect($url, [], $headers)->then(function(\Ratchet\Client\WebSocket $conn) use($contentType, $audioFileContents, $callback) {
$conn->on('message', function($msg) use ($conn, $callback) {
$this->handleIncomingWebSocketMessage($msg, $conn, $callback);
});
$conn->on('close', function($code = null, $reason = null) {
Log::debug("Connection closed ({$code} - {$reason})");
});
$this->startWatsonStream($conn, $contentType);
$this->sendBinaryMessage($conn, $audioFileContents);
Log::debug('send action stop');
$conn->send(json_encode(['action' => 'stop']));
}, function (\Exception $e) {
Log::error("Could not connect: {$e->getMessage()} " . $e->getTraceAsString());
});
...
public function handleIncomingWebSocketMessage($msg, $conn, $callback) {
Log::debug("Received: " . str_limit($msg, 100));
$msgArray = json_decode($msg, true);
$state = $msgArray['state'] ?? null;
if ($state == 'listening') {
if ($this->listening) {//then this is the 2nd time listening, which means audio processing has finished and has already been sent by server and received by this client.
Log::debug("FINAL RESPONSE: " . str_limit($this->responseJson, 500));
$conn->close(\Ratchet\RFC6455\Messaging\Frame::CLOSE_NORMAL, 'Finished.');
$callback($this->responseJson);
} else {
$this->listening = true;
Log::debug("Received first 'listening' message.");
}
} else {
$this->responseJson = $msg;
}
}
public function sendBinaryMessage($conn, $fileContents) {
$chunkSizeInBytes = 100; //probably just needs to be <= 4 MB according to Watson's rules
$chunks = str_split($fileContents, $chunkSizeInBytes);
Log::debug('Split audio into this many frames: ' . count($chunks));
$final = true;
foreach ($chunks as $key => $chunk) {
$frame = new \Ratchet\RFC6455\Messaging\Frame($chunk, $final, \Ratchet\RFC6455\Messaging\Frame::OP_BINARY);
$conn->send($frame);
}
}