【问题标题】:Safari behaving very weirdy with HTML5 audio tagSafari 对 HTML5 音频标签的行为非常奇怪
【发布时间】:2019-07-06 23:42:25
【问题描述】:

我正在构建一个网站,其中有一个 HTML5 音频元素,我使用 javascript 根据用户点击的曲目动态更新源。这由网络音频 API 包装,该 API 执行 fft 并使用它来控制三个 js 中的场景。

该网站在 chrome 和 firefox 中可以正常工作,但在 safari 中音频非常有问题。

第一个问题是 safari 不会接受源作为音频的子节点,如果您动态更新它,您必须将 src 放在音频标签中。我正在检查我的 js 中的 safari/IOS,并根据结果设置 opus 或 mp3 音频源。我尝试使用 m4a 作为文件格式,但它无法播放,尽管浏览器支持 m4a?

持续存在的问题是:

.pause() 方法不适用于音频元素,它只是在用户恢复播放时再次从曲目的开头播放。

尝试设置 .currentTime 以允许用户跳过曲目在 safari 中没有任何作用。但是它正在读取 currentTime 作为它设置播放头的位置。

当 animate() 函数(使用 requestAnimationFrame 递归调用)运行时,它在开始播放之前非常慢,超过一分钟的延迟,在 ios 上相同,但没有那么严重,并且 ios 不会遇到其他问题.

场景中的多边形数量约为 250k,这是相当高的,但是如果画布上的多边形数量使音频播放速度变慢,那就很奇怪了,尽管 requestAnimationFrame 未运行时音频存在其他问题。

请原谅我没有太多时间写这个草率的代码:

const playTrack = (trackNumber) => {
    audio.src = `assets/audio/${trackNumber}.${fileType}`;
    audio.load();
    audio.play();
};

audio.ontimeupdate = () => {
    const left = audio.currentTime * segment;
    playHead.style.width = `${left}px`;
};

playbar.addEventListener("click", (e) => {
    const pos = e.x - container.left;
    audio.currentTime =  pos / segment;
}, false);

    tracks.forEach(track => {
    track.addEventListener("click", (e) => {
        e.preventDefault();

        //pause or load
        if (!audio.paused && nowPlaying === track) {
            //pause track
            audio.pause();
            track.children[0].classList.remove('fa-pause');
            track.children[0].classList.add('fa-play');
        } else if (audio.paused && nowPlaying === track) {
            //play track
            audio.play();
            track.children[0].classList.remove('fa-play');
            track.children[0].classList.add('fa-pause');
        } else {
            //load and play track
            instructions.style.display = "none";
            trackNumber = parseInt(track.getAttribute('data-value'), 10);
            playTrack(trackNumber);
            nowPlaying = track;

            iconFlick(track);
        }

        trackDuration = duration[trackNumber];
        segment = width / trackDuration;

        if (clickFirst === 0) {
            clickFirst = 10;
            setupNodes(audio)
        }

        trackGlobal = track;
    });

const setupNodes = (audio) => {
    const audioCtx = new (window.AudioContext || window.webkitAudioContext)();
    const source = audioCtx.createMediaElementSource(audio);

    analyser = audioCtx.createAnalyser();
    source.connect(analyser);

    analyser.fftSize = 256;
    bufferLength = analyser.frequencyBinCount;
    dataArray = new Uint8Array(bufferLength);

    audioBegin = 1;

    analyser.connect(audioCtx.destination);
};

如果你发现了什么,请告诉我,这让我很难过。

【问题讨论】:

    标签: javascript html html5-audio web-audio-api


    【解决方案1】:

    如果您不使用<audio> 标签,您可能会有更好的运气和更多的控制权。如果您想要这些控件,则需要制作自己的播放按钮和滑块。并单独使用 Web Audio API 下载和解码并播放曲目。

    var url = "whatever.mp3";
    var source = audioCtx.createBufferSource();
    var buffers = {};
    
    var request = new XMLHttpRequest();
    request.open('GET', url, true);
    request.responseType = 'arraybuffer';
    
    request.onload = function () {
        audioCtx.decodeAudioData(request.response, function (buffer) {
            source.buffer = buffer;
            source.connect(audioCtx.destination);
            source.start(audioCtx.currentTime);
    
            // save this for later, so you can replay it without downloading
            buffers[url] = buffer; 
    
        }, function () {
            console.warn("error loading sound url: " + url);
        });
    }
    request.send();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-02-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-01
      • 1970-01-01
      相关资源
      最近更新 更多