【问题标题】:Detect model of iOS device using Javascript or HTML?使用 Javascript 或 HTML 检测 iOS 设备的型号?
【发布时间】:2012-06-10 22:02:31
【问题描述】:

所以我在我的网站上提供 H.264 .mp4 视频。我正在使用开源 HTML5 视频播放器 http://mediaelementjs.com/。一些访问者正在从 Safari for iPhone 查看。 iPhone 4 仅支持最高 720p 的视频播放,因此如果我将视频设置为小于此值,它们可以在 4 和 4S 上运行。但 4S 支持高达 1080p 的视频。那么如何将较大的视频提供给 4S,而将较小的视频提供给 4?我试过这个:

<video width="640" height="400" id="player" controls="controls" preload="auto">
    <source src="https://s3.amazonaws.com/my-big-1080p-video.mp4" type="video/mp4">
    <source src="https://s3.amazonaws.com/my-small-720p-video.mp4" type="video/mp4">
</video>

但它没有用。 iPhone 4 不够聪明,无法尝试第二个来源。如何让我的网站向不同的设备提供正确的视频?

【问题讨论】:

  • 对此有两个想法,虽然几乎没有答案:1)尝试检查和解析用户代理字符串。它可能包含有用的信息。 2) 考虑在两种 iPhone 型号上使用较低分辨率的视频。记住用户的数据使用计划。这个网站包含一些关于你想要做什么的信息:davidwalsh.name/detect-iphone
  • 您可以尝试使用媒体查询。
  • @Mageek 媒体查询不起作用,因为 iPhone 4 和 4s 都有视网膜显示。
  • @Moshe 我最终采纳了您的建议 #2,将低分辨率视频提供给所有设备
  • 我认为唯一的选择是让用户选择加入 1080p 质量,就像 Youtube 一样。 HTMLVideo Javascript 元素接受不同类型的格式检测,但我不确定 iOS Safari 是否支持按分辨率检测播放支持。

标签: javascript iphone html mediaelement.js device-detection


【解决方案1】:

在 iPhone 4 上播放 720p 视频 — 在 iPhone 4S 上播放 1080p 视频

在 iPhone 4 和 4S 上试试这个 (jsfiddle)

<video src="http://file.brow.sr/1080p.mp4" onerror="this.src='http://file.brow.sr/720p.mp4';" controls loop width="320" height="180">
</video>

说明

加载 1080p 视频,然后使用 Javascript 的 onError 回退到 720p。

Safari 会嗅探 1080p 文件的标题以确定它是否可播放,如果文件太大而无法解码,则会引发错误。然后我们捕获该错误以提供 720p 视频。

通过使用这种特征检测,回退不仅可以在一个设备(iPhone 4)上工作,而且可能在许多不同的浏览器上工作。

为什么多个&lt;source&gt; 不起作用

当使用多个&lt;source&gt; 标签具有相同的 MIME 类型时,浏览器将加载具有兼容 MIME 类型的第一个源并丢弃其他源,即使该视频不可播放。这是因为 source 元素 are expected 提供替代视频编解码器(例如 ogg、webm、mp4),不是替代帧大小/文件大小。

【讨论】:

  • 您在示例中忘记了http// 之间的冒号
【解决方案2】:

这里是如何去做的:

1) 使用 wurfl 检索设备型号

<script type='text/javascript' src=“//wurfl.io/wurfl.js"></script>

您可以使用 HTTP 或 HTTPS(两者都受支持)如果您计划使用脚本提供的设备信息来做出渲染决策,那么您可能希望将脚本包含在元素中。否则,您可以异步加载它。现在您可以在 JavaScript 中访问 WURFL 对象了。

示例响应如下所示:

{ complete_device_name:"Apple iPhone 5", form_factor:"智能手机", is_mobile:true }

当然你可以(并且应该)

console.log(WURFL);

找出您可以使用的其余属性。

2) 既然您知道您的用户到底是哪种设备型号 开启,您可以切换视频播放器配置。

怎么样?

<video width="IPHONE5_VIDEO_WIDTH"
       height="IPHONE5_VIDEO_HEIGHT"
       id="player" controls="controls"
       preload="auto">
       <source src="IPHONE5_VIDEO_URL" type="video/mp4">
</video>

超级干净易读对吧? 希望对您有所帮助。

【讨论】:

    【解决方案3】:

    我有一个执行此操作的 php 脚本。我在这里找到了 - http://detectmobilebrowsers.com/ - 是的,有 javascript、JQuery 等版本。它对我们来说效果很好,而且它的好处是似乎保持相当更新。我们遇到的唯一问题是 iPad 被故意设置为不将自己标识为移动设备。

    【讨论】:

      【解决方案4】:

      由于亲爱的@Duvrai 提到的原因,您的解决方案不起作用。 我已经寻找一种正确的方法来满足您的目的,似乎我们别无选择,除非使用一些 javascript 代码(这里不考虑服务器端编程)来决定应该交付哪个源。下面的 sn-p 检测浏览器 Type 及其 Version

      navigator.sayswho= (function(){
          var ua= navigator.userAgent, tem, 
          M= ua.match(/(opera|chrome|safari|firefox|msie|trident(?=\/))\/?\s*(\d+)/i) || [];
          if(/trident/i.test(M[1])){
              tem=  /\brv[ :]+(\d+)/g.exec(ua) || [];
              alert('IE '+(tem[1] || ''));
          }
          if(M[1]=== 'Chrome'){
              tem= ua.match(/\bOPR\/(\d+)/)
              if(tem!= null) alert('Opera '+tem[1]);
          }
          M= M[2]? [M[1], M[2]]: [navigator.appName, navigator.appVersion, '-?'];
          if((tem= ua.match(/version\/(\d+)/i))!= null) M.splice(1, 1, tem[1]);
          alert( M.join(' '));
      })();

      现在你可以用javascript写几行代码,然后根据浏览器TypeVersion来决定更换视频源。

      【讨论】:

      • 版本不会告诉你 iPhone 4 和 4S 的区别,因为两者都可以有 iOS 5-7。
      • @Duvrai 在这里,我们遇到了与浏览器功能相关的渲染引擎,该引擎可能因操作系统版本而异。我们不是吗?
      • 问题不是关于操作系统版本,而是硬件型号(iPhone 4/4S) 另外,您是否阅读了其他答案? @WebOrCode 和其他人已经给出了几乎相同的答案。
      • @Duvrai 我无法理解一件事!如果用户将他的浏览器升级到最新版本会发生什么?他不能播放高分辨率流?换句话说,播放分辨率类型是由硬件决定的吗?
      • 是的。最大分辨率取决于硬件功能。所以iOS版本无所谓。
      【解决方案5】:

      试试this 链接 该库应该能够检测到用户代理,并且您可以相应地提供适当的文件。

      【讨论】:

      • iOS 设备无法被用户代理检测到,因为不同设备有相同的 Safari 浏览器
      • Mikko,在说句子之前先看看这里:blog.mobileesp.com/?page_id=53。我个人将这个库用于几个应用程序,哦,我的上帝猜猜是什么......它说明了 ipod、iphone 和 ipad 之间的区别
      • 它仍然无法在 iPhone 4S(全高清)和 iPhone 4(无高清播放)之间有所不同 - 两者都报告相同的用户代理 AFAIK
      【解决方案6】:

      由于我不是 Apple 极客,因此我无法提供示例代码,但根据我尝试使网站在 XHTML 和 HTML5 之间兼容的经验,我可以告诉您,检查浏览器功能比检查浏览器版本更好。

      原因是浏览器版本太多而无法进行维护,并且用户代理字符串也可以修改。我建议您编写一个脚本,使用简单的 if 语句检查 HTML5 视频功能,然后根据结果呈现一个视频或另一个。

      【讨论】:

        【解决方案7】:

        如果您要检查的唯一功能是视频,那么像 WURFL(无线通用资源文件 - http://wurfl.sourceforge.net/)或 DeviceAtlas 之类的移动设备检测数据库可能会过大。但它是一种快速的方法,可以为比您能够编译检查的更大范围的设备进行强大的功能检测,并且如果您的站点需要验证其他功能,它会派上用场除了视频支持。

        【讨论】:

        • 这两个都是付费方案,有没有开源方案?
        【解决方案8】:

        MEJS 播放器无法正确处理错误,我想添加更多支持以检测实际发生的情况。在 iPhone 上,它有时甚至会引发错误事件,但没有实际错误,您可以正确播放视频。

        打开 mediaelement-and-player.js 并查找

                // error handling
                media.addEventListener('error',function() {
                    loading.hide();
                    controls.find('.mejs-time-buffering').hide();
                    error.show();
                    error.find('mejs-overlay-error').html("Error loading this resource");
                }, false);
        

        然后使用这个代码:

                // error handling
                media.addEventListener('error',function() {
                    var
                        videoError = error.closest('.mejs-inner').find('video,audio')[0].error,
                        msg = 'Error loading this resource.';
        
                    if (!videoError) { //webkit sometimes throws error event but video has no actual error and can play the video correctly - ignore the event
                        console.log('MEJS event: error throws but no error found - ignored');
                        return;
                    }
        
                    //hide elements visible while loading and playing - cannot play after error
                    loading.hide();
                    controls.addClass('hidden'); //controls are automatically displayed when mouse hover is detected - must hide it permanently using class with !important
                    error.closest('.mejs-inner').find('.mejs-overlay-play').hide(); //also hide overlay with play button
                    error.show();
        
                    //get relevant error message
                    switch(videoError.code) { //see http://www.w3.org/TR/html5/embedded-content-0.html#error-codes
                        case videoError.MEDIA_ERR_ABORTED: //loading stopped (by user, e.g. by pressing ESC or Back)
                            msg = 'Video loading aborted';
                            break;
                        case videoError.MEDIA_ERR_DECODE: //invalid format (actually presumed format is OK, but the data does not correspond with the defined format - probably corrupted file of data transfer)
                            msg = 'Video file is broken';
                            break;
                        case videoError.MEDIA_ERR_NETWORK: //network problem (was able to connect to the provided URL but could not get the video data)
                            msg = 'Network connection lost';
                            break;
                        case videoError.MEDIA_ERR_SRC_NOT_SUPPORTED: //invalid source URL (url provided does not lead to a supported video file)
                            msg = 'Video not supported';
                            break;
                    }
        
                    //display error
                    console.log('Video error: ' + msg + ', code: ' + videoError.code);
                    error.find('.mejs-overlay-error').html(msg);
                }, false);
        

        如果需要,您可以添加自己的处理方式,以在视频不受支持的情况下切换到 720p。

        然后在 mediaelementplayer.css 中添加这个(不确定是否真的需要或只是对我的主题进行改进):

        /* Display errors */
        .mejs-overlay-error {
            color: white;
            background: black;
            text-align: center;
            font-size: 1.2EM;
        }
        .mejs-controls.hidden {
            display: none !important;
        }
        /* End: Display errors */
        

        这是针对2.13.1版本的,不确定新版本是否更好。

        更新:最新版本 2.16.3 包含完全相同的无用错误处理程序。

        【讨论】:

          【解决方案9】:

          这将检测 iOS 版本。也许有用:

          if (navigator.userAgent.indexOf('5_0') != -1) {
              alert('IOS 5');
          } else {
              alert('Other');
          }
          

          编辑: 我已经对脚本进行了调整和测试。

          【讨论】:

          • 最好在提交答案之前测试您的代码。尤其是如果你想被点赞。
          • 是的。测试或引用来源。
          • 感谢您的提示。对此感到抱歉,但在发帖时我无法对此进行测试。刚刚看到这个问题,并试图给出一个有用的答案。
          【解决方案10】:

          把这个放在你的标签里:

          <meta name="viewport" content="initial-scale=1.0">
          <meta name="viewport" content="width=320.1">    
          <script>
          if (window.screen.height==568) { // iPhone 5
                              document.querySelector("meta[name=viewport]").content="width=320.1";
                            // your code here
                          }
          </script>
          

          【讨论】:

          • iPhone 4 和 4S 具有相同的分辨率。所以你的解决方案行不通。
          【解决方案11】:

          我使用这个代码:

              // iPhone 3
              if (window.screen.height==480 && window.screen.width==320 && window.devicePixelRatio==1)
              { 
                  $('#chartDivWrapper').html('<div id="chartdiv" style="height:300px;width:500px;"></div>');
              } 
              // iPhone 4, this is Retina
              else if (window.screen.height==480 && window.screen.width==320 && window.devicePixelRatio==2) 
              { 
                  $('#chartDivWrapper').html('<div id="chartdiv" style="height:300px;width:500px;"></div>');
              } 
              // iPhone 5
              else if (window.screen.height==568 && window.screen.width==320 && window.devicePixelRatio==2) 
              { 
                  $('#chartDivWrapper').html('<div id="chartdiv" style="height:400px;width:600px;"></div>');
              } 
              // iPad
              else if (window.screen.height==1024 && window.screen.width==768 && window.devicePixelRatio==1) 
              { 
                  $('#chartDivWrapper').html('<div id="chartdiv" style="height:425px;width:680px;"></div>');
              } 
              // iPad Retina
              else if (window.screen.height==1024 && window.screen.width==768 && window.devicePixelRatio==2) 
              { 
                  $('#chartDivWrapper').html('<div id="chartdiv" style="height:425px;width:680px;"></div>');
              } 
              // all other, this was before for all 
              else  
              { 
                  $('#chartDivWrapper').html('<div id="chartdiv" style="height:400px;width:600px;"></div>');
              }
          

          【讨论】:

          • 这并不能区分 iPhone 4 和 4S,这是真正的问题。
          • 你是对的,我的代码使用屏幕分辨率进行 iOS 设备检测。 iPhone 4 和 4S 屏幕分辨率相同,所以这个概念不适用。实际上,我只是将此代码用于屏幕分辨率,而不是设备检测,有人会发现它已满。
          猜你喜欢
          • 1970-01-01
          • 2012-12-31
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-10-29
          相关资源
          最近更新 更多