首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >检测H.265 HEVC不兼容

检测H.265 HEVC不兼容
EN

Stack Overflow用户
提问于 2022-04-08 22:59:21
回答 1查看 1.3K关注 0票数 1

我试图检测浏览器何时不会播放特定的视频。一个很好的例子就是试图检测Chrome不能播放H.265/HEVC编码的视频。

我试着用视频回退:

代码语言:javascript
复制
<video>
  <source [src]="attachmentVideo" type='video/mp4; codecs="avc1.4D401E, mp4a.40.2"'>
  Browser does not support the HTML5 Video element.
</video>

然而,我了解到,只有当浏览器不支持视频时,才能使用回退。因此,对于支持视频的Chrome,不执行回退,但视频将无法播放。

接下来,我试图侦听错误事件。

代码语言:javascript
复制
<video (error)="onError($event)">
  <source [src]="attachmentVideo" type='video/mp4; codecs="avc1.4D401E, mp4a.40.2"'>
  Browser does not support the HTML5 Video element.
</video>

但是,我也没有看到错误事件。

为了好玩,我还附加了onplay事件,以确保事件发生。这个事件确实有可能发生。

代码语言:javascript
复制
<video (canplay)="onCanPlay($event)">
  <source [src]="attachmentVideo" type='video/mp4; codecs="avc1.4D401E, mp4a.40.2"'>
  Your browser does not support the HTML5 Video element.
</video>

有没有可能没有外部库来检测浏览器是否支持视频和特定的编解码器?

EN

回答 1

Stack Overflow用户

发布于 2022-04-18 15:47:53

要检查是否通过JavaScript支持编解码器,请查看下面的选项对您是否有用:

(即:将所选的代码转换为角度语法/代码)

(1)如果编解码器已知.使用canPlayType检查编解码器的兼容性。

代码语言:javascript
复制
var vid = document.getElementById("myVideoElementID");

if( vid.canPlayType('video/mp4; codecs="hev1"') )
{ alert("can play HVC1 / H.265 "); }
else if( vid.canPlayType('video/mp4; codecs="avc1"') )
{ alert("can play AVC1 / H.264 "); }

(2)如果编解码器未知.检查编解码器类型的文件字节(然后执行步骤(1)以确认可玩性)

这意味着获取文件字节的一部分(例如,获取第一个64 at或最后一个64 at,取决于MP4头是在文件的前面还是后面)。

将数据读取到数组中,然后搜索该数组中的stsd部分,这是MP4保存H264数据序列参数集(SPS)的地方,您可以从该部分提取编解码器信息。

( a)找到stsd位置。

( b)从该位置跳过+16字节以查找avc1hev1

( c)从+16 pos跳过+91以获得SPS (3个字节)。

下面是一个使用选定(本地)文件的示例,该文件通过FileReader API读入数组。

代码语言:javascript
复制
<!DOCTYPE html>
<html>
<body>

<!-- button Choose MP4 Video -->
<div style="z-index: 1; overflow:hidden; position: absolute; top: 18px; left: 10px; " >
<text> <b> Choose a Video (.MP4) file...</b> <br> 
<input type="file" id="choose_video" accept=".mp4" />
</div>

<video id="myVideo" width="640" height="480" controls  style="position: absolute; top: 80px; left: 10px; " >
<source src="" type="video/mp4">
</video>

</body>

<script>

var temp_int = 0; var temp_str = ""; var temp_arr = [];

var reader; var path;
var fileBytes;  //# is updated to: uint8Array []
var file; //# a File object (using Reader) 

//# codec name (is String object)
var str_codec = "-1";

var myvid = document.getElementById( 'myVideo' );

addEventListener("load", on_page_Ready );

function on_page_Ready()
{
    //# listener for selecting MP4 file
    document.getElementById('choose_video').addEventListener('change', onSelectFile, false);
}

function onSelectFile(evt) 
{
    file = evt.target.files[0]; //# FileList object
    path = (window.URL || window.webkitURL).createObjectURL(file);
    
    reader = new FileReader();
    reader.readAsArrayBuffer(file);
        
    reader.onload = function(evt)
    {
        if (evt.target.readyState == FileReader.DONE) 
        {
            fileBytes = new Uint8Array( evt.target.result );
            
            //# extract codec info
            get_MP4_Codec( fileBytes ); 
            
            //# load video data and play ...
            myvid.setAttribute("src", path);
            myvid.load();
            
            myvid.play();
        }
    }
}

function get_MP4_Codec (inBA)
{
    let idx = 0; //# index (position) in bytes
    
    while(true)
    {
        //# auto stop if "stsd" not found after 32 kilobytes
        if ( (idx > 32000) || (idx >= inBA.length-1) ) { break; }
        
        //# look for starting "s" (is byte value 0x73)
        if( inBA[ idx ] == 0x73 ) //# find "s"
        {
            //# check if next following 3 bytes are the required values
            if( (inBA[ idx+1 ] == 0x74) &&  //# find "t"
                (inBA[ idx+2 ] == 0x73) &&  //# find "s"
                (inBA[ idx+3 ] == 0x64)     //# find "d"
            )
            {
                //# when found... 
                
                //# note the "stsd" position
                temp_int = idx; 
                
                //# skip forward by 16 bytes to get codec type
                //# codec type can be "avc1" or "hev1" or "hvc1"
                
                idx += 16;
                str_codec =  String.fromCharCode( inBA[ idx+0 ] );
                str_codec += String.fromCharCode( inBA[ idx+1 ] );
                str_codec += String.fromCharCode( inBA[ idx+2 ] );
                str_codec += String.fromCharCode( inBA[ idx+3 ] );
                
                //# need that dot "." also
                str_codec += ".";
                
                //# skip forward by 91 bytes to get codec SPS details
                //# example"avc1.64001f" the SPS is "64001F"
                idx += 91;
                
                temp_str = (inBA[idx].toString(16)).toUpperCase();
                str_codec += temp_str.length === 2 ? temp_str : '0' + temp_str;
                
                idx += 1;
                temp_str = (inBA[idx].toString(16)).toUpperCase();
                str_codec += temp_str.length === 2 ? temp_str : '0' + temp_str;
                
                idx += 1;
                temp_str = (inBA[idx].toString(16)).toUpperCase();
                str_codec += temp_str.length === 2 ? temp_str : '0' + temp_str;
                
                break;
                
            }
            
        }
        
        idx++;
    }
    
    alert("found STSD @ byte pos : " + temp_int +"\n"+ "codec type : " + str_codec );

}

</script>

</html>
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71803915

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档