Javascript 如何在 iPad 上使用 Youtube iFrame API 修复“如果播放没有很快开始,请尝试重新启动您的设备”?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/33902844/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 15:37:32  来源:igfitidea点击:

How to fix "If playback doesn't begin shortly, try restarting your device" using Youtube iFrame API on iPad?

javascriptiosyoutubeyoutube-apiyoutube-javascript-api

提问by David

I've created a little YouTube streaming script which randomly plays YouTube music videos or from a queue. It's worked fine for months up until this week in which it doesn't seem to want to load the videos when using an iPad/iPhone. I get the following error instead:

我创建了一个小的 YouTube 流媒体脚本,它随机播放 YouTube 音乐视频或从队列中播放。直到本周它似乎不想在使用 iPad/iPhone 时加载视频,它已经运行了好几个月。我收到以下错误:

If playback doesn't begin shortly, try restarting your device

如果播放没有很快开始,请尝试重新启动您的设备

What I've tried:

我试过的:

I've tried Safari, Chrome, Firefox and Opera and they all error. I've tried clearing website data/cache, restarting the device, fulling restarting the device. Nothing works. The weird thing is, it works absolutely fine on a Windows desktop which leads me to believe it's not an error in the code, but something that has either changed with the API or with Safari. My code has not been edited recently either which could have caused it to stop working.

我尝试过 Safari、Chrome、Firefox 和 Opera,但它们都出错了。我尝试清除网站数据/缓存,重新启动设备,重新启动设备。什么都行不通。奇怪的是,它在 Windows 桌面上运行得非常好,这让我相信这不是代码中的错误,而是 API 或 Safari 发生了变化。我的代码最近也没有被编辑,这可能导致它停止工作。

I've tried debugging it using jsconsole.com, nothing suspicious pops up. In some cases, the player will load, the title of the video will display and so will the image, but after about 30 seconds, the error above displays along with the loading spinner.

我试过使用 jsconsole.com 调试它,没有任何可疑的弹出。在某些情况下,播放器会加载,视频的标题会显示,图像也会显示,但大约 30 秒后,上面的错误会与加载微调器一起显示。

I'm aware that playVideo(); doesn't work (autoplay) on iOS devices. This is fine, and again, the script has worked previously, i've only had to press play on the firstvideo. But now, it seems like iOS is trying to auto-play the video. So, I've also tested by removing the playVideo() calls, problem still persists.

我知道 playVideo(); 在 iOS 设备上不起作用(自动播放)。这很好,而且脚本以前也可以使用,我只需要在第一个视频上按播放即可。但是现在,iOS 似乎正在尝试自动播放视频。因此,我还通过删除 playVideo() 调用进行了测试,问题仍然存在。

Tested on iPad 2, iPad mini and iPhone 4 (all with the latest iOS available on the device and all worked previously).

在 iPad 2、iPad mini 和 iPhone 4 上进行了测试(所有设备都配备了最新的 iOS,并且之前都可以运行)。

I'm at a loss and trying to get this fixed before the weekend for a house party :) So I'd appreciate any help or hints as to what might be causing the failure on iOS.

我不知所措,并试图在周末举行家庭聚会之前解决这个问题:) 因此,对于可能导致 iOS 故障的任何帮助或提示,我将不胜感激。

Here is the javascript code:

这是javascript代码:

// 2. This code loads the IFrame Player API code asynchronously.
var tag = document.createElement('script');

tag.src = "https://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);

// 3. This function creates an <iframe> (and YouTube player)
//    after the API code downloads.
var player;
function onYouTubeIframeAPIReady() {
    player = new YT.Player('player', {
        height: '390',
        width: '640',
        events: {
            'onReady': onPlayerReady,
            'onStateChange': onPlayerStateChange
        }
    });
}

// 4. The API will call this function when the video player is ready.
function onPlayerReady(event) {
    check_queue_timer = setTimeout(check_queue(),3000);
}

// 5. The API calls this function when the player's state changes.
//    The function indicates that when playing a video (state=1),
//    the player should play for six seconds and then stop.
var done = false;
function onPlayerStateChange(event) {
    if (event.data === 0) {
        // TRACK AS DONE, REFRESH QUEUE AND GET NEXT SONG
        // POST TO WRITE TO FILE
        $.ajax({
            type: 'POST',
            url: site_url+'ajax_next_track',
            dataType: 'json',
            data: 'queue_id='+$('#queue_id').val(),
            cache: false,
            success:
            function(data){

                if(data.status == 'success'){
                    $("#queue_table").empty();
                    if(data.queue.length == 0){
                        check_queue_timer = setTimeout(check_queue(),3000);
                    }
                    $.each(data.queue, function(i, item) {
                        if(i == 0){
                            event.target.loadVideoById(item.video_id);
                            event.target.playVideo();
                            $('#queue_id').val(item.queue_id);
                        }
                        $('#queue_table').append('<tr><td>'+item.title+'</td></tr>');
                    });
                }
                else{
                    console(data.message);
                }
            },
            error:
            function( jqXHR, textStatus, errorThrown ){
                $('#error_msg').html('Something broke.').fadeIn();
            }

        });
    }
}
function stopVideo() {
    player.stopVideo();
}

function check_queue(){
    $.ajax({
        type: 'POST',
        url: site_url+'ajax_next_track',
        dataType: 'json',
        data: 'no_delete=1',
        cache: false,
        success:
        function(data){

            if(data.status == 'success'){
                $("#queue_table").empty();
                if(data.queue.length == 0){
                    clearTimeout(check_queue_timer);
                    check_queue_timer = setTimeout(check_queue(),3000);
                }
                $.each(data.queue, function(i, item) {
                    if(i == 0){
                        player.loadVideoById(item.video_id);
                        player.playVideo();
                        $('#queue_id').val(item.queue_id);
                        clearTimeout(check_queue_timer);
                    }
                    $('#queue_table').append('<tr><td>'+item.title+'</td></tr>');
                });
            }
            else{
                console(data.message);
            }
        },
        error:
        function( jqXHR, textStatus, errorThrown ){
            $('#error_msg').html('Something broke.').fadeIn();
        }

    });
}

UPDATE 1 (25TH NOV 2015)

更新 1(2015 年 11 月 25 日)

I've decided to start from scratch and work with the example code on https://developers.google.com/youtube/iframe_api_reference. It seems that loadVideoById() is no longer working on iPads. It was before. If I don't include the loadVideoById() or playVideo() it works. Ideally, i'd like it to work with loadVideoById().

我决定从头开始,使用https://developers.google.com/youtube/iframe_api_reference上的示例代码。似乎 loadVideoById() 不再适用于 iPad。这是以前。如果我不包含 loadVideoById() 或 playVideo() ,它就可以工作。理想情况下,我希望它与 loadVideoById() 一起使用。

采纳答案by Adrian Holovaty

I've banged my head against the computer for hours trying to solve this one... Here's what I've found.

我用头撞电脑好几个小时试图解决这个问题......这是我发现的。

This is happening because of Apple's draconian iOS limitation: web pages can only start playing audio/video when responding directly to user feedback. (Note this limitation only affects the firsttime audio/video is played on a page.)

这是因为 Apple 严格的 iOS 限制:网页只能在直接响应用户反馈时开始播放音频/视频。(请注意,此限制仅影响一次在页面上播放音频/视频。)

Usually, to work around Apple's limitation, it's sufficient to make sure your play() call happens directly in an event handler (e.g., a click handler). This works for the Web Audio API and normal HTML5 videos -- but something about the YouTube player prevents this from working for YouTube.

通常,要解决 Apple 的限制,确保 play() 调用直接在事件处理程序(例如,单击处理程序)中发生就足够了。这适用于 Web Audio API 和普通的 HTML5 视频——但有关 YouTube 播放器的某些内容阻止了它对 YouTube 的工作。

As a result, the solution for YouTube apparently is to require the user to click the YouTube video itself to initiate playback. From then on, you can control it using the YouTube iframe API (play, pause, seek, etc.). But you cannot control the YouTube video using the API until afterthe user has clicked the video.

因此,YouTube 的解决方案显然是要求用户单击 YouTube 视频本身来启动播放。从那时起,您可以使用 YouTube iframe API 控制它(播放、暂停、搜索等)。但是在用户单击视频之前您无法使用 API 控制 YouTube视频。

For a foolproof user experience, you can hide all of your player-controlling UI and tell users to click the YouTube video itself to start playback. Then, once, the user has clicked the video once, you can activate your UI. Of course, you should design this only to apply to iOS.

为了获得万无一失的用户体验,您可以隐藏所有播放器控制 UI,并告诉用户单击 YouTube 视频本身开始播放。然后,一旦用户点击视频一次,您就可以激活您的用户界面。当然,您应该将其设计为仅适用于 iOS。

Thanks for the headaches, Apple!

谢谢你的头痛,苹果!

回答by Junior

I had a similar issue and did some digging, turns out Apple have removed the ability to autoplay embed items via scripts etc so the end user doesn't unexpectedly use up their data. The user needs to trigger the play button themselves.

我遇到了类似的问题并进行了一些挖掘,结果发现 Apple 已经取消了通过脚本等自动播放嵌入项目的功能,因此最终用户不会意外地用完他们的数据。用户需要自己触发播放按钮。

The best way to fix this issue would be check if the user is on mobile or desktop and set a variable (true/false).

解决此问题的最佳方法是检查用户是使用移动设备还是桌面设备并设置变量(真/假)。

This is what I did

这就是我所做的

var mobileDevice = false;
if(typeof window.orientation !== 'undefined'){
 var mobileDevice = true;
}

if(!mobileDevice) ytPlayer.playVideo();

Hopefully that helps.

希望这有帮助。

Source (https://developer.apple.com)

来源(https://developer.apple.com)

To prevent unsolicited downloads over cellular networks at the user's expense, embedded media cannot be played automatically in Safari on iOS—the user always initiates playback.

为防止用户自行承担费用通过蜂窝网络进行未经请求的下载,无法在 iOS 上的 Safari 中自动播放嵌入式媒体——用户始终启动播放。

More answers here - YouTube API not working with iPad / iPhone / non-Flash device

更多答案在这里 - YouTube API 不适用于 iPad / iPhone / 非 Flash 设备

回答by ABeanSits

If the issue is what the other two answers (Adrian & Junior) say then it should be easily solved by accessing the UIWebView(or WKWebView) and setting the mediaPlaybackRequiresUserActionflag. This can be done if you rolled your own solution or if your using the official framework (https://github.com/youtube/youtube-ios-player-helper).

如果问题是其他两个答案 (Adrian & Junior) 所说的,那么应该可以通过访问UIWebView(or WKWebView) 并设置mediaPlaybackRequiresUserAction标志来轻松解决。如果您推出自己的解决方案或使用官方框架 ( https://github.com/youtube/youtube-ios-player-helper),则可以完成此操作。

Swift

迅速

let playerView = YTPlayerView()
playerView.webView.mediaPlaybackRequiresUserAction = false

回答by AR Rose

I faced the problem after installing a DPS audio application to my laptop. The apps modified my existing Audio Driver to their "Speakers (Digital Power Station)"Audio Devices.

在我的笔记本电脑上安装 DPS 音频应用程序后,我遇到了这个问题。这些应用程序将我现有的音频驱动程序修改为它们的“扬声器(数字电站)”音频设备。

By reading a Redditpost, I replace the Audio Device to My Laptop's origin. Thus, the problem fixed for me.

通过阅读Reddit帖子,我将音频设备替换为我的笔记本电脑的来源。因此,问题为我解决了。