评论

使用threejs渲染视频

使用threejs实现视频播放

琢磨了很久,翻了很多相关文档,才实现了用threejs渲染视频的方法

思路如下

1 在wxml文件里写两个canvas

 <canvas type="webgl" class="myCanvas" id="myCanvas"></canvas>
<canvas style="position: absolute;left: 0;top:300rpx;background-color: red;"  type="2d" id="target1"></canvas>

2 实例threeJs相关实例和方法,具体参考,可以百度,

3 添加2d相关实例方法,

export default class VideoPlayer {
  
    constructor(component){// component 是组件里的this, 
      this.decoder = wx.createVideoDecoder()
      this.component = component
      const videoUrl = 'https://cdn2.h5no1.com/static-cdn/cpbz/v.mp4';
      this.dataUriList = []
    }
    getCanvasNode(id) {
      return new Promise((resolve) => {
        this.component.createSelectorQuery()
        .select('#' + id)
        .node(res => resolve(res.node))
        .exec();
    });
  }
  async downLoad(url){ // 下载视频并压缩视频,如果不压缩可能会卡
   return new Promise(resolve=>{
    wx.downloadFile({
      url,
      success:res=>{
        wx.compressVideo({
          quality:'low',
          // resolution:0.9,
          // fps:60,
          src:res.tempFilePath,
          success:result=>{
            console.log(result)
            resolve(result.tempFilePath)
          }
        })
       
      },
      fail:()=>{
        resolve(url)
      }
    })
   }) 
  }
  async playVideo(id,videoUrl,cb){
    const canvas = await this.getCanvasNode(id) //获取2dcanvas节点
    const path = await this.downLoad(videoUrl) // 下载视频并返回本地地址
    const context = canvas.getContext('2d') // 2d上下文
 
    const render = ({ data, width, height }) => { // 渲染2d时,返回DataURI数据,作为纹理数据
      canvas.height = height
      canvas.width = width
      const imageData = canvas.createImageData(data, width, height)
      context.putImageData(imageData, 0, 0)
      if(canvas.toDataURL()){
      
        cb && cb(canvas.toDataURL()) // cb回调方法
      }
      
    }
    const decoder = wx.createVideoDecoder() // 创建视频解码器
    await decoder.start({ // 开始解码
      abortAudio: true,
      source:path || videoUrl // tempFilePath,
    })


    return Promise.resolve({
      decoder,
      stop(){
        return decoder.remove()
      },
      play:async ()=>{  
        let imageData = decoder.getFrameData() // 获取下一帧的解码数据
        if (imageData){
        
          render(imageData)
        }       
      }
    }) 
  }


}

4 在threejs中引入上面的代码

import VideoPlayer from "./video.js"
/*
省略前面的代码
*/
  this.videoPlayer = new VideoPlayer(this)
  this.vp = null
  var geometry = new THREE.PlaneGeometry( 520, 320, 1);
  var material = new THREE.MeshBasicMaterial( {side: THREE.DoubleSide} );
   
    var plane3 = new THREE.Mesh( geometry, material );
    plane3.position.set(0,rangeSize/2/2,-rangeSize/2)
    scence.add( plane3 );


 this.videoPlayer.playVideo('target1','https://video-qn.51miz.com/preview/video/00/00/12/22/V-122260-B7D997DF.mp4',async (res)=>{
      if(res){
       textureLoader.load(res,texture=>{ // 加载datauri数据到纹理,一定要写在回调里,不然也看着卡顿
        texture.minFilter = THREE.NearestFilter
        plane3.material.map = texture
       });
      
      }
    
    }).then(res=>{
      this.vp =res
    })
    // 动画帧方法
    this.wgbglCanvas.requestAnimationFrame(()=>{
        if(this.vp && this.vp.play){

            this.vp.play()
        }
    })
                        


5 视频解码器 文档 https://developers.weixin.qq.com/miniprogram/dev/api/media/video-decoder/wx.createVideoDecoder.html

这个方法很重要,没有这个方法,根本就不能实现webgl视频播放



最后一次编辑于  2022-08-30  
点赞 1
收藏
评论

1 个评论

登录 后发表内容