Playing Audio in Blazor Server with js interop, cuts first part of audio on first play

huangapple go评论83阅读模式
英文:

Playing Audio in Blazor Server with js interop, cuts first part of audio on first play

问题

我已经按照这个教程在Blazor Server中使用js互操作播放音频:
https://www.appvnext.com/blog/2020/4/20/playing-audio-files-in-a-blazor-application

我想按下一个按钮并播放一个.mp3文件。

在第一次页面加载或者如果我将浏览器标签保持不动超过10秒钟,它会切断音频文件的前部分。如果我反复按下它,它就不会再切断了。

这发生在Firefox、Brave、Chrome和Edge上。

它在我的开发机器和我的Windows服务器上都发生。

我尝试直接在audio标签中放置src标签,或者像下面这样分离。

这个例子在javascript中的.play之前进行了.load。我尝试了一种更简单的以前的播放方式(见下面的'PlayAudio' js),那也会发生这种情况。我以为.load可能会解决这个问题,但似乎没有任何区别。

英文:

I've followed this tutorial to play audio in Blazor Server using js interop:
https://www.appvnext.com/blog/2020/4/20/playing-audio-files-in-a-blazor-application

I want to press a button and have it play an .mp3 file.

On first page load or if I left the browser tab alone for more than say 10 seconds, it cuts off the first part of the audio file. If I repeatedly press it it doesn't cut off any more.

It happens in Firefox, Brave, Chrome and Edge.

It happens on my dev machine and my Windows Server.

I've tried putting the src tag directly in the audio tag, or separating as below.

This example does a .load before the .play in javascript. I tried a simpler previous way to play it (sese js below 'PlayAudio') and that does it too. I thought .load might fix it but it seems to make no difference.

The code
js (currently using PlayAudioFile, but also happens with PlayAudio):

window.PlayAudio = (elementName) => {
    document.getElementById(elementName).play();
}

window.PauseAudio = (elementName) => {
    document.getElementById(elementName).pause();
}

window.PlayAudioFile = (src) => {
    var audio = document.getElementById('player');
    if (audio != null) {
        var audioSource = document.getElementById('playerSource');
        if (audioSource != null) {
            audioSource.src = src;
            audio.load();
            audio.play();
        }
    }
}

.razor file

<button style="margin-right:10px" class="btn btn-outline-primary" @onclick="@(() => SpeakName())">Play</button>

<audio id="player">
    <source id="playerSource" src="">
</audio>

@code{
    ...

    private async Task SpeakName()
    {
        await _jsRuntime.InvokeAsync<string>("PlayAudioFile", $"../sounds/1.mp3");
    }


...    

}

private async Task SpeakName(string Id)
{
_file = Id + ".mp3?x=" + DateTime.Now.Microsecond;

await _jsRuntime.InvokeAsync<string>("PlayAudioFile", $"../sounds/{_file}");

}

I've extensively searched and can't find anything.

How can I stop it cutting off the first bit of audio when playing the audio file for the first time?

Thanks

答案1

得分: 1

潜在问题可能在于浏览器在首次播放音频文件时可能需要一些时间来加载。文件有多大?或许尝试预加载:

window.audioPreloaded = false;

window.preloadAudio = (src) => {
    if (!window.audioPreloaded) {
        var audio = document.getElementById('player');
        if (audio != null) {
            var audioSource = document.getElementById('playerSource');
            if (audioSource != null) {
                audioSource.src = src;
                audio.load();
                window.audioPreloaded = true;
            }
        }
    }
};

window.PlayAudio = (elementName) => {
    document.getElementById(elementName).play();
};

window.PauseAudio = (elementName) => {
    document.getElementById(elementName).pause();
};

window.PlayAudioFile = (src) => {
    var audio = document.getElementById('player');
    if (audio != null) {
        var audioSource = document.getElementById('playerSource');
        if (audioSource != null) {
            if (audioSource.src !== src) {
                audioSource.src = src;
                audio.load();
            }
            audio.play();
        }
    }
};

编辑:你也可以等待整个文件预加载,通过监听 canplaythrough 事件:

window.PlayAudioFile = (src) => {
    var audio = document.getElementById('player');
    if (audio != null) {
        var audioSource = document.getElementById('playerSource');
        if (audioSource != null) {
            if (audioSource.src !== src) {
                audioSource.src = src;
                audio.load();
            }

            if (audio.readyState >= 4) {
                audio.play();
            } else {
                audio.addEventListener('canplaythrough', function playWhenReady() {
                    audio.removeEventListener('canplaythrough', playWhenReady);
                    audio.play();
                });
            }
        }
    }
};

Razor:

@inject IJSRuntime _jsRuntime

<button style="margin-right:10px" class="btn btn-outline-primary" @onclick="@(() => SpeakName())">播放</button>

<audio id="player">
    <source id="playerSource" src=""></source>
</audio>

@code{
    private string _file = "";

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            _file = $"../sounds/1.mp3?x={DateTime.Now.Millisecond}";
            await _jsRuntime.InvokeVoidAsync("preloadAudio", _file);
        }
    }

    private async Task SpeakName()
    {
        await _jsRuntime.InvokeAsync<string>("PlayAudioFile", _file);
    }
    // ...
}

未经测试,关于你的环境有很多我不了解的东西,可能需要进行一些调试。

英文:

Potentially issue with the fact that browser might need time to load the audio file when it's first played? How large is the file? Maybe try preloading:

window.audioPreloaded = false;

window.preloadAudio = (src) =&gt; {
    if (!window.audioPreloaded) {
        var audio = document.getElementById(&#39;player&#39;);
        if (audio != null) {
            var audioSource = document.getElementById(&#39;playerSource&#39;);
            if (audioSource != null) {
                audioSource.src = src;
                audio.load();
                window.audioPreloaded = true;
            }
        }
    }
};

window.PlayAudio = (elementName) =&gt; {
    document.getElementById(elementName).play();
};

window.PauseAudio = (elementName) =&gt; {
    document.getElementById(elementName).pause();
};

window.PlayAudioFile = (src) =&gt; {
    var audio = document.getElementById(&#39;player&#39;);
    if (audio != null) {
        var audioSource = document.getElementById(&#39;playerSource&#39;);
        if (audioSource != null) {
            if (audioSource.src !== src) {
                audioSource.src = src;
                audio.load();
            }
            audio.play();
        }
    }
};

EDIT: You could also wait for whole file to preload, by listening for the canplaythrough event:

window.PlayAudioFile = (src) =&gt; {
    var audio = document.getElementById(&#39;player&#39;);
    if (audio != null) {
        var audioSource = document.getElementById(&#39;playerSource&#39;);
        if (audioSource != null) {
            if (audioSource.src !== src) {
                audioSource.src = src;
                audio.load();
            }

            if (audio.readyState &gt;= 4) {
                audio.play();
            } else {
                audio.addEventListener(&#39;canplaythrough&#39;, function playWhenReady() {
                    audio.removeEventListener(&#39;canplaythrough&#39;, playWhenReady);
                    audio.play();
                });
            }
        }
    }
};

Razor:

@inject IJSRuntime _jsRuntime

&lt;button style=&quot;margin-right:10px&quot; class=&quot;btn btn-outline-primary&quot; @onclick=&quot;@(() =&gt; SpeakName())&quot;&gt;Play&lt;/button&gt;

&lt;audio id=&quot;player&quot;&gt;
    &lt;source id=&quot;playerSource&quot; src=&quot;&quot;&gt;
&lt;/audio&gt;

@code{
    ...
    private string _file = &quot;&quot;;

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            _file = $&quot;../sounds/1.mp3?x={DateTime.Now.Millisecond}&quot;;
            await _jsRuntime.InvokeVoidAsync(&quot;preloadAudio&quot;, _file);
        }
    }

    private async Task SpeakName()
    {
        await _jsRuntime.InvokeAsync&lt;string&gt;(&quot;PlayAudioFile&quot;, _file);
    }

    ...
}

not tested it, lot of things I don't know about your ENV, so you might need to play around with it.

huangapple
  • 本文由 发表于 2023年3月15日 20:42:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/75744866.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定