У меня есть веб-служба PHP, которая возвращает HTTP-ответ mp3. Это работает, но когда я включаю дросселирование сети Chrome в DevTools, он возвращает только часть ответа:
$stream_start1 = Psr7\stream_for(fopen('./sounds/ping.mp3', 'r'));
$stream_start2 = Psr7\stream_for(fopen('./sounds/ping.mp3', 'r'));
$stream_start3 = Psr7\stream_for(fopen('./sounds/ping.mp3', 'r'));
$stream_start4 = Psr7\stream_for(fopen('./sounds/ping.mp3', 'r'));
$stream_start5 = Psr7\stream_for(fopen('./sounds/ping.mp3', 'r'));
$stream_start6 = Psr7\stream_for(fopen('./sounds/ping.mp3', 'r'));
$stream_start7 = Psr7\stream_for(fopen('./sounds/ping.mp3', 'r'));
$stream_start8 = Psr7\stream_for(fopen('./sounds/ping.mp3', 'r'));
$stream_start9 = Psr7\stream_for(fopen('./sounds/ping.mp3', 'r'));
$stream_start10 = Psr7\stream_for(fopen('./sounds/ping.mp3', 'r'));
$stream_start11 = Psr7\stream_for(fopen('./sounds/ping.mp3', 'r'));
$stream_start12 = Psr7\stream_for(fopen('./sounds/ping.mp3', 'r'));
$stream_start13 = Psr7\stream_for(fopen('./sounds/ping.mp3', 'r'));
return new Psr7\AppendStream([$stream_start1 , $stream_start2 , $stream_start3 , $stream_start4 , $stream_start5 , $stream_start6 , $stream_start7 , $stream_start8 , $stream_start9 , $stream_start10, $stream_start11, $stream_start12, $stream_start13]);
С приведенным выше кодом при включенном дросселировании dev я получаю 7 пингов вместо 13.
На самом деле реальный код получает поток от стороннего сервиса и помещает его между двумя файлами:
return new Psr7\AppendStream([file1Stream, 3rdPartyStream, file2Stream])
Итак, мне не обязательно знать длину, чтобы установить Content-Length, поэтому я использую Transfer-Encoding: chunked.
Когда я смотрю в инструментах разработки на укороченные ответы на запросы, я постоянно вижу, что они заканчиваются чем-то похожим на какие-то ХРОМЫЕ метаданные или добавленную тишину:
e¨Deš•†š¹‡ÌC`̹3†'2 CBR9S¨Âöei´g¡ÿ–W©^¥ÔzWI}I8¸¶vv,¸¼Ù£J*ÙÙû±W•'X&+X±£@È ·bbÂìýbŸâÿâŸëLAME3.100UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUÿóbÄ”AIÖtUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU
Мне интересно, возможно ли, что браузер путает часть этой информации LAME (или что-то еще) с концом последовательности фрагментов из-за задержек в получении фрагментов. Возможно ли, что в двоичном аудиофайле смешано что-то, напоминающее пустой фрагмент, указывающий на последний фрагмент? Есть ли способ избежать или закодировать данные, чтобы избежать потенциальных последовательностей, подобных этой? Может через компрессию?
Мой другой вариант - прочитать сторонний поток (в середине сэндвича) полностью в память перед его пересылкой. Таким образом, я могу рассчитать длину и установить Content-Length, так что это план Б.
ОБНОВЛЕНИЕ: я попытался установить Content-Length в моем небольшом примере с 13 файлами, но я все еще получаю 7 пингов в качестве ответа. Длина, которую я рассчитал с:
$length = strlen($stream_start0->getContents()) * 13
Это 122252. Но возвращаемое содержимое файла имеет длину около 65529 байт (шестнадцатеричный редактор говорит 65536...?). В любом случае, это слишком коротко. Кроме того, заголовок Transfer-Encoding исчез, что означает, что я думаю, что он больше не разбивается на части?
ОБНОВЛЕНИЕ 2: Также возможно, что проблема в том, что я объединяю mp3-файлы в необработанном виде. Я думаю, что технически все становится сомнительным, когда вы это делаете, особенно если аудио содержит теги ID3 и тому подобное, хотя в файлах ping, использованных выше, не должно быть никаких тегов ID3. Однако в нашей среде stg, где я наблюдаю эту проблему без инструментов разработчика, отключение не всегда происходит в перерывах между файлами.