简体   繁体   English

Safari 网络音频可视化工具适用于 mp3 文件但不适用于流

[英]Safari web audio visualizer works with mp3 file but not with stream

I am trying to stream audio and visualize it via canvas, however it appears to only work with a static file (mp3 in this case) when I need to get it to work with a continuous stream.我正在尝试流式传输音频并通过画布将其可视化,但是当我需要让它与连续流一起工作时,它似乎只适用于静态文件(在本例中为 mp3)。

It looks as the bufferArray is full of zeros using getByteFrequencyData, or 128 using getByteTimeDomainData.使用 getByteFrequencyData 时,bufferArray 看起来充满了零,或者使用 getByteTimeDomainData 时,bufferArray 充满了 128。

Important Notes重要笔记

  1. It is not an actual MP3 file the audio source is coming from but a buffer stream that is updated periodically, for proprietary reasons I can not share the actual URL, but it would look like this for example " http://somedomain/stream ".它不是音频源来自的实际 MP3 文件,而是定期更新的缓冲流,出于专有原因,我无法共享实际的 URL,但它看起来像这样,例如“ http://somedomain/stream ” . The format MP3 is actually delivered in the headers.格式 MP3 实际上是在标题中提供的。

  2. Cannot use fetch or other XHR request as the URL needs to be sharable when it goes live.不能使用 fetch 或其他 XHR 请求,因为 URL 在上线时需要可共享。

  3. Cannot change header format无法更改标题格式

Please see the following code snippets.请参阅以下代码片段。

Example files static mp3 file: https://s3-us-west-2.amazonaws.com/s.cdpn.io/481938/Find_My_Way_Home.mp3 stream endpoint: http://rfcmedia.streamguys1.com/MusicPulse.mp3示例文件静态 mp3 文件: https ://s3-us-west-2.amazonaws.com/s.cdpn.io/481938/Find_My_Way_Home.mp3 流端点: http ://rfcmedia.streamguys1.com/MusicPulse.mp3

HTML HTML

<button id="btn">Start</button>
<canvas id="canvas" style="background:black;width:512px;height:255px;"></canvas>

JS JS

window.onload = () => {
    document.getElementById('btn').addEventListener('click', () => {
        const audio = new Audio()
        audio.autoplay = false
        audio.crossOrigin = 'anonymous'
        audio.src = 'http://rfcmedia.streamguys1.com/MusicPulse.mp3'


        const player = document.getElementById('audio_player')
        const canvas = document.getElementById('canvas')
        const canvasCtx = canvas.getContext('2d')
        const audioContext = new (window.AudioContext ||
            window.webkitAudioContext)()
        const analyser = audioContext.createAnalyser()
        analyser.connect(audioContext.destination)

        const audioSourceNode = audioContext.createMediaElementSource(audio)
        audioSourceNode.connect(analyser)

        const data = new Uint8Array(analyser.frequencyBinCount)

        const render = () => {
            analyser.getByteFrequencyData(data)

            canvasCtx.clearRect(0, 0, canvas.width, canvas.height)
            const center = canvas.height / 2
            let diff = 10
            let shape = {
                x: diff,
                y1: center,
                y2: center
            }

            for (let i = 0; i < data.length; i++) {
                let height = data[i] / 2

                if (height) {
                    shape.y1 = center - height
                    shape.y2 = center + height

                    const { x, y1, y2 } = shape

                    const lingrad = canvasCtx.createLinearGradient(0, 0, 0, 180)
                    lingrad.addColorStop(0, '#5d8db6')
                    lingrad.addColorStop(0.515, '#5d8db6')
                    lingrad.addColorStop(0.52, '#fff')
                    lingrad.addColorStop(0.53, '#fff')
                    lingrad.addColorStop(0.535, 'rgba(93, 141, 182, 0.6)')
                    lingrad.addColorStop(1, 'rgba(93, 141, 182, 0.6)')

                    canvasCtx.beginPath()
                    canvasCtx.moveTo(x, y1)
                    canvasCtx.quadraticCurveTo(x - diff, center, x, y2)
                    canvasCtx.moveTo(x, y1)
                    canvasCtx.quadraticCurveTo(x + diff, center, x, y2)
                    canvasCtx.closePath()
                    canvasCtx.fillStyle = lingrad
                    canvasCtx.fill()

                    shape.x = x + 8
                }
            }

            requestAnimationFrame(render)
        }

        requestAnimationFrame(render)
        audio.play()
    })
}

You may want to look into using Media Source Extensions , which allows you to read and decode chunks of the file while it streams.您可能需要研究使用Media Source Extensions ,它允许您在文件流式传输时读取和解码文件块。 This MSE MP3 tutorial may be useful too. 这个 MSE MP3 教程可能也很有用。 That tutorial references XHR, but you could also use fetch() with the streams API to play the audio该教程引用了 XHR,但您也可以将 fetch() 与流 API 一起使用来播放音频

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM