首页 > 解决方案 > 流式音频不会使用音频标签播放

问题描述

我正在尝试制作音频流服务,为此我创建了一个服务器来处理音频标签的请求并使用请求的适当块进行响应。但是,当我尝试在浏览器中播放它时,虽然我可以看到浏览器发出的请求,但我仍然无法播放它。知道有什么问题吗?

提供块的服务器代码

@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)

<audio src={`http://localhost:6543/stream/song?id=${currentSong.id}`} controls ref={audioRef} />

示例 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 /*

标签: javahttpaudiostreaming

解决方案


推荐阅读