使用Javascript或HTML检测iOS设备的型号?

20

所以我正在我的网站上提供H.264 .mp4格式的视频。我正在使用开源的HTML5视频播放器http://mediaelementjs.com/。一些访问者正在使用iPhone Safari浏览器观看。 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 不够智能,无法尝试第二个源。我该如何使我的网站为不同的设备提供正确的视频?


4
有两个想法,但不完全是答案:1)尝试检查和解析用户代理字符串。 它可能包含有用的信息。2)考虑在两种iPhone型号上使用更低分辨率的视频。 记得考虑用户的数据使用计划。这个网站包含了一些关于你正在做的事情的信息:http://davidwalsh.name/detect-iphone - Moshe
你可以尝试使用媒体查询。 - Alexandre Khoury
@Mageek 媒体查询不起作用,因为iPhone 4和4s都有Retina显示屏。 - jasssonpet
1
@Moshe,我最终采用了你的建议#2,向所有设备提供低分辨率视频。 - Binyamin Bauman
1
我认为唯一的选择是让用户选择是否选择1080p质量,就像Youtube一样。HTMLVideo Javascript元素接受不同种类的格式检测,但我不确定iOS Safari是否支持通过分辨率进行播放支持检测。 - Mikko Ohtamaa
11个回答

9

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

Try this on an iPhone 4 and a 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),而且可能适用于许多不同的兼容浏览器。

为什么多个<source>无法工作

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


你的例子中 http// 之间缺少了一个冒号。 - Damiaan Dufaux

2

以下是具体步骤:

1)使用wurfl检索设备型号

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

你可以使用HTTP或HTTPS(两者都支持)。如果您计划使用脚本提供的设备信息来做渲染决策,那么您可能需要将脚本包含在元素中。否则,您可以异步加载它。现在您可以在JavaScript中访问WURFL对象。
示例响应如下:
{完整设备名称:“Apple iPhone 5”,表单因素:“智能手机”, 是移动设备:是}
当然你可以(而且应该)这样做。
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>

很干净易读,对吧?希望这能有所帮助。

1
你的解决方案无法实现,因为 @Duvrai 所提到的原因。我已经搜索了一种正确的方法来达到你的目的,似乎除非使用一些 JavaScript 代码(这里不考虑服务器端编程),否则我们没有选择,以便决定应该传递哪个源。下面的片段检测浏览器类型和版本:

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中编写一些代码,并根据浏览器的类型版本决定更改视频源。

1
版本号无法告诉你iPhone 4和4S之间的区别,因为两者都可以运行iOS 5-7。 - Duvrai
@Duvrai,我们面临的问题是与渲染引擎相关的浏览器能力,这可能因操作系统版本而异,不是吗? - Amirhossein Mehrvarzi
1
问题不是关于操作系统版本,而是硬件型号(iPhone 4/4S)。另外,你有看到其他的答案吗?@WebOrCode和其他人已经给出了几乎相同的答案。 - Duvrai
@Duvrai 我不明白一件事!如果用户升级到最新的浏览器会发生什么?他不能播放高分辨率流吗?换句话说,硬件是决定播放分辨率类型的关键因素吗? - Amirhossein Mehrvarzi
是的。最大分辨率取决于硬件能力。因此,iOS 版本并不重要。 - Duvrai

1
我有一个 PHP 脚本可以实现这个功能。我在http://detectmobilebrowsers.com/上找到了它,而且还有 JavaScript、JQuery 等版本。它对我们来说效果很好,而且似乎也会不断更新。唯一遇到的问题是有一个 iPad 故意设置为不识别自己为移动设备。

0

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包含完全相同的无用错误处理程序。


0
一个类似 WURFL(Wireless Universal Resource File - http://wurfl.sourceforge.net/)或者 DeviceAtlas 的移动设备检测数据库也许过于臃肿,如果你只是检查视频功能的话。但是这确实是一种快速获取强大能力检测方法的途径,可以检测到比你编译检查合理范围内更多的设备,如果你的网站需要验证除视频支持之外的其他能力,这会非常有用。

这两个都是付费解决方案,难道没有开源解决方案吗? - deweydb

0

我无法提供示例代码,因为我不是苹果发烧友,但根据我的经验来看,尝试使网站在XHTML和HTML5之间兼容时,最好检查浏览器功能而不是浏览器版本。

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


0
尝试使用this链接。该库应该能够检测用户代理并相应地提供适当的文件。

iOS设备无法被用户代理检测所探测,因为不同的设备拥有相同的Safari浏览器。 - Mikko Ohtamaa
Mikko,在发表言论之前请先查看这里:http://blog.mobileesp.com/?page_id=53。我个人在几个应用中使用了这个库,哦天哪,猜猜看……它可以区分iPod、iPhone和iPad的区别。 - HobieCat
据我所知,它仍然无法区分iPhone 4S(全高清)和iPhone 4(不支持高清播放),两者报告的用户代理是相同的。 - Mikko Ohtamaa

-1

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

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

编辑: 我已经调整并测试了脚本。


最好在提交答案之前测试您的代码,特别是如果您想获得赞同。 - mrk
没错。要么测试,要么引用来源。 - svidgen
谢谢你的建议。很抱歉,我在发帖时无法进行测试。只是看到这个问题,试图给出一个有帮助的答案。 - Ricardo Oliveira

-1
我使用这段代码:
    // 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,而这才是实际问题。 - Duvrai
1
你说得对,我的代码使用屏幕分辨率来检测iOS设备。iPhone 4和4S具有相同的屏幕分辨率,因此这个概念不适用。实际上,我只是在使用这个代码来获取屏幕分辨率,而不是进行设备检测,某些人会发现它很有用。 - WebOrCode

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接