視訊在H5遊戲中的應用

冠豸山上人發表於2018-04-11

前言

遊戲中如果需要使用一些預先錄製好的動畫,動畫格式可以選擇 gif 檔案和視訊檔案,視訊檔案和 gif 檔案相比,size 更小(相同質量,gif 檔案比 mp4 檔案大5倍以上)。

如果視訊能在 canvas 中或者 webgl 中播放,這樣視訊可以和其它遊戲元素整合,實現以前需要很複雜的方式才能實現的功能,比如在一個旋轉的 3D 立方體中播放視訊。

當前主流的瀏覽器 chrome,使用 U4 2.0 核心的 app(包括 UC 瀏覽器,手淘,支付寶,釘釘等)都支援視訊在 canvas 中播放。

javascript 實現視訊在 canvas 中播放

視訊在 canvas 中播放,可以更好地和其它遊戲元素整合,主要步驟如下(完整原始碼參考附件 video_canvas.html):

1.建立後臺視訊

var video = document.createElement(`video`);
video.src = `.xxxx.mp4`;

2.建立 canvas

var canvas = document.createElement(`canvas`);
var canvasContext = canvas.getContext(`2d`);

3.視訊播放後定時把影像 render 到 canvas

var canvas = document.createElement(`canvas`);
var canvasContext = canvas.getContext(`2d`);

video.addEventListener(`play`, function() {
  setInterval(function() {
    canvasContext.drawImage(video, 0, 0, width, height);
  }, 30);
});

執行效果:

image.png

javascript 實現視訊在 weggl 中播放

為使示例簡單,使用了three.js – javascript 3D library 實現 webgl 功能,把視訊渲染到一個立方體表面,執行效果:

image.png

完整例子參考附錄例子(video_canvas.html),核心程式碼:

1.使用視訊建立紋理

texture = new THREE.Texture(video);
texture.wrapS = THREE.RepeatWrapping;
texture.wrapT = THREE.RepeatWrapping;
texture.repeat.set( 1, 1 );

2.建立立方體,視訊紋理和立方體關聯

var cubeGeometry = new THREE.CubeGeometry(1, 1, 1);
var material = new THREE.MeshLambertMaterial({map: texture, shading: THREE.FlatShading});
cube = new THREE.Mesh(cubeGeometry, material);

3.渲染的時候要定時重新整理紋理

texture.needsUpdate = true;

如果你自己測試的時候, video texture 紋理更新失敗 ,錯誤資訊是:

DOMException: Failed to execute `texImage2D` on `WebGLRenderingContext`: The video element contains cross-origin data, and may not be loaded

給 video 新增屬性 crossorigin

video.setAttribute(`crossorigin`, `anonymous`);

白鷺引擎實現視訊在 canvas 中播放

參考 官方文件

執行效果:

image.png

當前版本(5.0.15)的 白鷺引擎,視訊在 canvas 中播放功能,PC瀏覽器執行無壓力,在移動瀏覽器上有 bug(只能全屏播放,無法和其它頁面元素整合,完整的 bugfix diff 參考:egret-patch.diff):

1、執行 WebVideo.prototype.play() 的時候,mobile 模式,直接進全屏,修改方法:

不執行 this.checkFullScreen(this._fullscreen),只執行:

_this.videoPlay();
egret.startTick(_this.markDirty, _this);

如果是 iOS 瀏覽器,還需要

document.body.appendChild(video)

因為,iOS 瀏覽器,video 不在 document 裡面,無法播放起來,另外 size 不能太小,否則也無法播放起來。

2、WebVideo.prototype.$render() 在移動瀏覽器,總是把 video.poster render 到 canvas,沒有把video 影像 render 到 cavas,修改方法:

遮蔽原來的,執行下面這個:

var data = bitmapData ? bitmapData : posterData;
if (data) {
    node.image = data;
    node.imageWidth = data == posterData ? width : bitmapData.width;
    node.imageHeight = data == posterData ? height : bitmapData.height;
    if (data == bitmapData) {
        egret.WebGLUtils.deleteWebGLTexture(bitmapData.webGLTexture);
        bitmapData.webGLTexture = null;
    }
    node.drawImage(0, 0, data.width, data.height, 0, 0, width, height);
}

U4 2.0 核心支援力度

特性支援

U4 2.0 核心視訊自動播放特性(不需要手勢觸發)和在 canvas 中播放特性預設關閉,可以通過下發配置開啟。

引擎支援

支援白鷺引擎

iOS 平臺瀏覽器支援力度

特性支援

iOS 平臺的瀏覽器,視訊可以在 canvas 中播放,但 iOS safari 瀏覽器,視訊開始播放,預設進入全屏播放,影響遊戲使用,但基於 safari 核心的瀏覽器(比如 iOS UC 瀏覽器),設定:

webView.allowsInlineMediaPlayback = YES

可以實現開始播放不需要進入全屏播放(頁內播放)。

另外,設定:

webView.mediaPlaybackRequiresUserAction = NO;

可以實現視訊自動播放(不需要手勢觸發);

引擎支援

支援白鷺引擎


相關文章