YouTube API 不适用于 iPad/iPhone/非 Flash 设备

本文介绍了YouTube API 不适用于 iPad/iPhone/非 Flash 设备的处理方法,对大家解决问题具有一定的参考价值

问题描述

这段代码在桌面浏览器中运行良好(代码由@Rob-W 提供),点击缩略图,相邻的视频将开始播放,使用 YouTube 的 API.

HTML

<div id="tabs2">
<img class='thumb' src='http://i2.cdnds.net/11/34/odd_alan_partridge_bio_cover.jpg'><iframe id="frame1" width="640" height="390" frameborder="0" title="YouTube 视频播放器"type="text/html"src="http://www.youtube.com/embed/u1zgFlCw8Aw?enablejsapi=1"></iframe></div>
<img class='thumb' src='http://i2.cdnds.net/11/34/odd_alan_partridge_bio_cover.jpg'><iframe id="frame2" width="640" height="390" frameborder="0" title="YouTube 视频播放器"type="text/html"src="http://www.youtube.com/embed/u1zgFlCw8Aw?enablejsapi=1"></iframe></div></div>

CSS

#tabs2 div {位置:相对;}/* 出于安全原因,元素不能放置在框架上 *//*.拇指{位置:绝对;}*/.玩 {边框:3px 纯红色;}

JS

function getFrameID(id) {var elem = document.getElementById(id);如果(元素){if (/^iframe$/i.test(elem.tagName)) 返回 id;//帧,OK//else: 寻找框架var elems = elem.getElementsByTagName("iframe");如果(!elems.length)返回null;//没有找到iframe,失败for (var i = 0; i < elems.length; i++) {if (/^https?://(?:www.)?youtube(?:-nocookie)?.com(/|$)/i.test(elems[i].src));}元素 = 元素[i];//唯一的,或者最好的iFrame如果(elem.id)返回elem.id;//已有ID,返回//else: 创建一个新的IDdo {//保持后缀 `-frame` 直到 ID 唯一id += "-frame";} while (document.getElementById(id));elem.id = id;返回标识;}//如果没有元素,则返回 null.返回空值;}//定义 YT_ready 函数.var YT_ready = (function() {var onReady_funcs = [],api_isReady = 假;/* @param func function 准备执行的函数* @param func Boolean 如果为真,则执行所有队列函数* @param b_before Boolean 如果为真,函数将添加到第一个队列中的位置*/返回函数(函数,b_before){如果(函数 === 真){api_isReady = 真;for (var i = 0; i < onReady_funcs.length; i++) {//从数组中删除第一个 func,并执行 funconReady_funcs.shift()();}}否则 if (typeof func == "function") {如果(api_isReady)函数();否则 onReady_funcs[b_before ?"unshift" : "推"](func);}}})();//当 API 完全加载时会调用这个函数函数 onYouTubePlayerAPIReady() {YT_ready(真)}var 玩家 = {};//定义一个播放器存储对象,以启用以后的函数调用,//无需再次创建新的类实例.YT_ready(函数() {$(".thumb + iframe[id]").each(function() {var 标识符 = this.id;var frameID = getFrameID(标识符);if (frameID) {//如果框架存在玩家[frameID] = new YT.Player(frameID, {事件:{"onReady": createYTEvent(frameID, 标识符)}});}});});//返回一个启用多个事件的函数函数 createYTEvent(frameID, 标识符) {返回函数(事件){var player = 玩家 [frameID];//播放器对象var the_div = $('#'+标识符).parent();the_div.children('.thumb').click(function() {var $this = $(this);$this.fadeOut().next().addClass('play');if ($this.next().hasClass('play')) {播放器.playVideo();}});}}//加载 YouTube Frame API(function(){//关闭,不泄漏到作用域var s = document.createElement("script");s.src = "http://www.youtube.com/player_api";/* 加载播放器 API*/var before = document.getElementsByTagName("script")[0];before.parentNode.insertBefore(s, before);})();

JSFiddle

问题是它无法在 iOS 设备上播放(我认为是因为缺少 Flash 播放器,它只是挂起).

我可以通过再次点击视频来强制它播放,这会提示它使用 QuickTime 播放.

但是如何让它自动与 QuickTime 一起播放呢?

解决方案

很抱歉,这在 iOS 中是不可能的.根据 Apple 的文档

<块引用>

"...嵌入式媒体无法在 iOS 上的 Safari 中自动播放 -用户总是启动播放."

无论网络连接如何,限制都是一致的,因为它既是带宽决定,也是用户体验决定.

2016 年 10 月更新:值得注意的是,现在 iOS 10 已经发布并获得了可观的市场份额,人们可以利用 iOS 10 上视频播放方式的变化来获得自动播放行为.如果视频没有音轨或标签被静音,则可以进行自动播放.此 webkit 博客 中提供了更多信息.YouTube API 可能很快就能很好地处理这个问题.

This piece of code works great in DESKTOP browsers (code courtesy of @Rob-W), click the thumbnail and the adjacent video will start playing, using YouTube's API.

HTML

<div id="tabs2">
    <div>
    <img class='thumb' src='http://i2.cdnds.net/11/34/odd_alan_partridge_bio_cover.jpg'>
    <iframe id="frame1" width="640" height="390" frameborder="0" title="YouTube video player"type="text/html"src="http://www.youtube.com/embed/u1zgFlCw8Aw?enablejsapi=1"></iframe>
    </div>

    <div>
        <img class='thumb' src='http://i2.cdnds.net/11/34/odd_alan_partridge_bio_cover.jpg'>
   <iframe id="frame2" width="640" height="390" frameborder="0" title="YouTube video player"type="text/html"src="http://www.youtube.com/embed/u1zgFlCw8Aw?enablejsapi=1"></iframe>
    </div>
</div>

CSS

#tabs2 div {
    position: relative;
}
/* For security reasons, an element cannor be placed over a frame */
/*.thumb {
    position: absolute;
}*/    
.play {
    border: 3px solid red;
}

JS

function getFrameID(id) {
    var elem = document.getElementById(id);
    if (elem) {
        if (/^iframe$/i.test(elem.tagName)) return id; //Frame, OK
        // else: Look for frame
        var elems = elem.getElementsByTagName("iframe");
        if (!elems.length) return null; //No iframe found, FAILURE
        for (var i = 0; i < elems.length; i++) {
            if (/^https?://(?:www.)?youtube(?:-nocookie)?.com(/|$)/i.test(elems[i].src)) break;
        }
        elem = elems[i]; //The only, or the best iFrame
        if (elem.id) return elem.id; //Existing ID, return it
        // else: Create a new ID
        do { //Keep postfixing `-frame` until the ID is unique
            id += "-frame";
        } while (document.getElementById(id));
        elem.id = id;
        return id;
    }
    // If no element, return null.
    return null;
}

// Define YT_ready function.
var YT_ready = (function() {
    var onReady_funcs = [],
        api_isReady = false;
/* @param func function     Function to execute on ready
         * @param func Boolean      If true, all qeued functions are executed
         * @param b_before Boolean  If true, the func will added to the first
                                     position in the queue*/
    return function(func, b_before) {
        if (func === true) {
            api_isReady = true;
            for (var i = 0; i < onReady_funcs.length; i++) {
                // Removes the first func from the array, and execute func
                onReady_funcs.shift()();
            }
        }
        else if (typeof func == "function") {
            if (api_isReady) func();
            else onReady_funcs[b_before ? "unshift" : "push"](func);
        }
    }
})();
// This function will be called when the API is fully loaded

function onYouTubePlayerAPIReady() {
    YT_ready(true)
}

var players = {};
//Define a player storage object, to enable later function calls,
//  without having to create a new class instance again.
YT_ready(function() {
    $(".thumb + iframe[id]").each(function() {
        var identifier = this.id;
        var frameID = getFrameID(identifier);
        if (frameID) { //If the frame exists
            players[frameID] = new YT.Player(frameID, {
                events: {
                    "onReady": createYTEvent(frameID, identifier)
                }
            });
        }
    });
});

// Returns a function to enable multiple events
function createYTEvent(frameID, identifier) {
    return function (event) {
        var player = players[frameID]; // player object
        var the_div = $('#'+identifier).parent();
        the_div.children('.thumb').click(function() {
            var $this = $(this);
            $this.fadeOut().next().addClass('play');
            if ($this.next().hasClass('play')) {
                player.playVideo();
            }
        });
    }
}
// Load YouTube Frame API
(function(){ //Closure, to not leak to the scope
  var s = document.createElement("script");
  s.src = "http://www.youtube.com/player_api"; /* Load Player API*/
  var before = document.getElementsByTagName("script")[0];
  before.parentNode.insertBefore(s, before);
})();

JSFiddle

The problem is that it fails to play on iOS devices (because of the lack of Flash player, I think, it just hangs).

I can force it to play by tapping the video once more, which prompts it to play using QuickTime.

But how do I get it to play with QuickTime automatically?

解决方案

I'm sorry to say this is not possible in iOS. According to Apple's documentation,

"...embedded media cannot be played automatically in Safari on iOS - the user always initiates playback."

The restriction is consistent regardless of network connection as it is both a bandwidth decision as well as a user experience decision.

Update, October, 2016: It's worth noting, now that iOS 10 is out and gaining significant market share, that people can leverage changes in the way video playback works on iOS 10 to get autoplay behavior. If the video has no audio tracks or the tag is muted, autoplay can be possible. More information is available in this webkit blog. The YouTube API may handle this nicely soon.

这篇关于YouTube API 不适用于 iPad/iPhone/非 Flash 设备的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,WP2

admin_action_{$_REQUEST[‘action’]}

do_action( "admin_action_{$_REQUEST[‘action’]}" )动作钩子::在发送“Action”请求变量时激发。Action Hook: Fires when an ‘action’ request variable is sent.目录锚点:#说明#源码说明(Description)钩子名称的动态部分$_REQUEST['action']引用从GET或POST请求派生的操作。源码(Source)更新版本源码位置使用被使用2.6.0 wp-admin/admin.php:...

日期:2020-09-02 17:44:16 浏览:1127

admin_footer-{$GLOBALS[‘hook_suffix’]}

do_action( "admin_footer-{$GLOBALS[‘hook_suffix’]}", string $hook_suffix )操作挂钩:在默认页脚脚本之后打印脚本或数据。Action Hook: Print scripts or data after the default footer scripts.目录锚点:#说明#参数#源码说明(Description)钩子名的动态部分,$GLOBALS['hook_suffix']引用当前页的全局钩子后缀。参数(Parameters)参数类...

日期:2020-09-02 17:44:20 浏览:1032

customize_save_{$this->id_data[‘base’]}

do_action( "customize_save_{$this-&gt;id_data[‘base’]}", WP_Customize_Setting $this )动作钩子::在调用WP_Customize_Setting::save()方法时激发。Action Hook: Fires when the WP_Customize_Setting::save() method is called.目录锚点:#说明#参数#源码说明(Description)钩子名称的动态部分,$this->id_data...

日期:2020-08-15 15:47:24 浏览:775

customize_value_{$this->id_data[‘base’]}

apply_filters( "customize_value_{$this-&gt;id_data[‘base’]}", mixed $default )过滤器::过滤未作为主题模式或选项处理的自定义设置值。Filter Hook: Filter a Customize setting value not handled as a theme_mod or option.目录锚点:#说明#参数#源码说明(Description)钩子名称的动态部分,$this->id_date['base'],指的是设置...

日期:2020-08-15 15:47:24 浏览:866

get_comment_author_url

过滤钩子:过滤评论作者的URL。Filter Hook: Filters the comment author’s URL.目录锚点:#源码源码(Source)更新版本源码位置使用被使用 wp-includes/comment-template.php:32610...

日期:2020-08-10 23:06:14 浏览:903

network_admin_edit_{$_GET[‘action’]}

do_action( "network_admin_edit_{$_GET[‘action’]}" )操作挂钩:启动请求的处理程序操作。Action Hook: Fires the requested handler action.目录锚点:#说明#源码说明(Description)钩子名称的动态部分$u GET['action']引用请求的操作的名称。源码(Source)更新版本源码位置使用被使用3.1.0 wp-admin/network/edit.php:3600...

日期:2020-08-02 09:56:09 浏览:848

network_sites_updated_message_{$_GET[‘updated’]}

apply_filters( "network_sites_updated_message_{$_GET[‘updated’]}", string $msg )筛选器挂钩:在网络管理中筛选特定的非默认站点更新消息。Filter Hook: Filters a specific, non-default site-updated message in the Network admin.目录锚点:#说明#参数#源码说明(Description)钩子名称的动态部分$_GET['updated']引用了非默认的...

日期:2020-08-02 09:56:03 浏览:834

pre_wp_is_site_initialized

过滤器::过滤在访问数据库之前是否初始化站点的检查。Filter Hook: Filters the check for whether a site is initialized before the database is accessed.目录锚点:#源码源码(Source)更新版本源码位置使用被使用 wp-includes/ms-site.php:93910...

日期:2020-07-29 10:15:38 浏览:809

WordPress 的SEO 教学:如何在网站中加入关键字(Meta Keywords)与Meta 描述(Meta Description)?

你想在WordPress 中添加关键字和meta 描述吗?关键字和meta 描述使你能够提高网站的SEO。在本文中,我们将向你展示如何在WordPress 中正确添加关键字和meta 描述。为什么要在WordPress 中添加关键字和Meta 描述?关键字和说明让搜寻引擎更了解您的帖子和页面的内容。关键词是人们寻找您发布的内容时,可能会搜索的重要词语或片语。而Meta Description则是对你的页面和文章的简要描述。如果你想要了解更多关于中继标签的资讯,可以参考Google的说明。Meta 关键字和描...

日期:2020-10-03 21:18:25 浏览:1620

谷歌的SEO是什么

SEO (Search Engine Optimization)中文是搜寻引擎最佳化,意思近于「关键字自然排序」、「网站排名优化」。简言之,SEO是以搜索引擎(如Google、Bing)为曝光媒体的行销手法。例如搜寻「wordpress教学」,会看到本站的「WordPress教学:12个课程…」排行Google第一:关键字:wordpress教学、wordpress课程…若搜寻「网站架设」,则会看到另一个网页排名第1:关键字:网站架设、架站…以上两个网页,每月从搜寻引擎导入自然流量,达2万4千:每月「有机搜...

日期:2020-10-30 17:23:57 浏览:1263