#java #http #audio #streaming
Вопрос:
Я пытаюсь создать службу потоковой передачи аудио, для этого я создал сервер, который обрабатывает запросы аудиотегов и отвечает соответствующим запрошенным фрагментом. Однако, когда я пытаюсь воспроизвести его в браузере, хотя я вижу запросы, выполняемые браузером, я все равно не могу воспроизвести его. Есть идеи, что случилось?
Серверный код для предоставления фрагментов
@GetOperation(endpoint = "/stream/song") public HttpResponse getChunkAudioTag(@RequestHeader(RANGE_HEADER_KEY) String range, @QueryParameter("id") String songId) throws Exception { JSONObject songInfo = fakeDbDAO.getSongById(songId); String fileName = (String) songInfo.get("filename"); try (FileInputStream fileInputStream = new FileInputStream( new File(String.format(RESOURCES_FOLDER_PATH_TEMPLATE, fileName, FileFormat.MP3.getExtension())) )) { Headers headers = new Headers( ACCEPT_RANGES_HEADER_KEY, BYTES, Headers.CONTENT_TYPE, "audio/mpeg", Headers.CONNECTION, ConnectionType.KEEP_ALIVE.getValue() ); int fileSize = fileInputStream.available(); if (range == null) { return HttpResponse .builder() .headers(headers) .requestStatus(RequestStatus.OK) .build(); } String rangeString = range.split(AUDIO_TAG_RANGE_SEPARATOR)[1]; // Splits "bytes=x-y" and returns the actual range ChunkRange chunkRange = new ChunkRange(rangeString, fileSize); byte[] audioChunk = getAudioChunk(fileInputStream, chunkRange); headers.addHeader(CONTENT_RANGE_HEADER_KEY, String.format(CONTENT_RANGE_TEMPLATE, chunkRange.getFrom(), chunkRange.getTo() - 1, fileSize)); headers.addHeader(Headers.CONTENT_LENGTH, String.valueOf(audioChunk.length)); return HttpResponse .builder() .requestStatus(RequestStatus.PARTIAL_CONTENT) .headers(headers) .body(convertByteArrayToString(audioChunk)) .build(); } } private byte[] getAudioChunk(FileInputStream fileInputStream, ChunkRange chunkRange) throws IOException { byte[] result = new byte[chunkRange.getLength()]; fileInputStream.skip(chunkRange.getFrom()); fileInputStream.read(result); return result; } private String convertByteArrayToString(byte[] chunkByteArray) { return Base64 .getEncoder() .encodeToString(chunkByteArray); }
Аудиотег (я использую React)
lt;audio src={`http://localhost:6543/stream/song?id=${currentSong.id}`} controls ref={audioRef} /gt;
Пример HTTP-запроса
GET /stream/song?id=1 HTTP/1.1 Host: localhost:6543 Connection: keep-alive Pragma: no-cache Cache-Control: no-cache sec-ch-ua: "Google Chrome";v="95", "Chromium";v="95", ";Not A Brand";v="99" Accept-Encoding: identity;q=1, *;q=0 sec-ch-ua-mobile: ?0 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36 sec-ch-ua-platform: "macOS" Accept: */* Sec-Fetch-Site: same-site Sec-Fetch-Mode: no-cors Sec-Fetch-Dest: audio Referer: http://localhost:3000/ Accept-Language: en-US,en;q=0.9 Range: bytes=0-
Пример HTTP-ответа
HTTP/1.1 206 Partial Content Accept-Ranges: bytes Access-Control-Allow-Origin: * Connection: keep-alive Content-Type: audio/mpeg Content-Range: bytes 0-99999/4127452 Content-Length: 100000 */ base64 encoded chunk /*