VR视频直播播放器

本文介绍了一个基于three.js的VR视频直播播放器,支持HLS和rtmp-flv直播流,适用于手机浏览器和微信。项目包括虚拟场景搭建,如VR背景视频球体、VR文字、3D动画模型和Pandatv直播画面的集成。同时,介绍了简单的交互功能和如何处理直播列表。

VR视频直播播放器

采用 three.js 作为框架的VR视频播放器,支持hls,rtmp-flv直播流播放,可作为直播网站的VR增强版。

  • three.js 框架构造,易于扩展
  • 配合VR内点击功能,可以简单交互
  • 采用HLS/rtmp-flv播放直播流
  • 适配手机浏览器/微信


项目地址

VR直播网页播放器
lhbxxx / vr-stream-web-player

虚拟场景搭建

项目基于 [ WebVR Boilerplate ]

基本场景用three.js进行构建,其中包括以下元素
1. VR抠像视频与背景视频结合
2. VR文字
3. VR 3D动画模型
4. 基于pandatv的直播画面

VR背景视频球体

利用背景视频和绿幕视频进行合成,使抠像视频中的内容可以显示在背景视频中.

  • 利用getContentVideo()获取对应的视频球体
function getContentVideo(){
  var contentBox;
  //读取id为video_content的视频作为抠像视频
  video_content = document.getElementById( 'video_content' );
  texture_content = new THREE.VideoTexture( video_content );
  texture_content.minFilter = THREE.LinearFilter;
  texture_content.magFilter = THREE.LinearFilter;
  //生成球状背景
  var geometry = new THREE.SphereBufferGeometry( 50, 32, 32);
  //生成对应参数的材质
  v_shaderMaterial = new THREE.ShaderMaterial( {
          uniforms: {
            //uSampler为抠像视频源
            'uSampler':{
              value:texture_content
            },
            //uSource为背景视频源
            'uSource':{
              value:texture
            },
            'uRotate':{
              value:effectController.bg_rotate
            },
            'uTop':{
              value:effectController.c_top
            },
            'uScale':{
              value:effectController.c_scale
            },
            'uDiff':{
              value:effectController.c_diff
            }
          },
          //利用vertextShader与fragmentShader进行抠像合成,将背景与抠像视频合成为同一个视频流输出
          vertexShader: document.getElementById( 'vertexShader' ).textContent,
          fragmentShader: document.getElementById( 'fragmentShader' ).textContent,
          side: THREE.DoubleSide
  } );

  v_shaderMaterial.extensions.derivatives = true;
  //生成场景物体
  contentBox = new THREE.Mesh( geometry, v_shaderMaterial);
  //位置及角度修正
  contentBox.position.set(0, controls.userHeight, 0);
  contentBox.rotation.y=0.6*Math.PI;
  video_content.play();
  return contentBox;
}
  • 将对应的合成视频球体加入到场景中
skybox = getContentVideo();
scene.add(skybox);

VR文字

项目里只取了部分文字可以显示.

任玩堂游戏手机好超级知道你我他

想生成更多对应的VR文字资源,可以利用 [ Facetype.js ]

生成并替换models/appgame.typeface.json文件

var logo_text;
var logo;
function addAppgameLogo(text){
  var loader = new THREE.FontLoader();
  //读取文字资源
      loader.load( 'models/appgame.typeface.json', function ( font ) {
        text=text.replace(/[^任玩堂游戏手机好超级知道你我他]/g,'');
        //设置参数
        var logo_text = new THREE.TextGeometry( text, {
          font: font,
          size: 0.1,
          height:0.01
        } );
        if(logo){
          scene.remove(logo);
          logo.geometry.dispose();
        }
        logo=new THREE.Mesh(logo_text,new THREE.MeshBasicMaterial());
        logo.position.set(0, controls.userHeight, 0);
        logo.position.z-=2;
        //添加文字到场景
        scene.add(logo);
      } );
}
//启动后自动添加
$(function(){ 
  addAppgameLogo('任玩堂');
});

3D动画模型

项目添加了three.js里面的一种动画模型


var clock = new THREE.Clock();
var dae;
var mixer;
var dae_x=4.09;
var dae_y=-1.42;
mixer = new THREE.AnimationMixer( scene );
function addMonster(){
  var loader = new THREE.ColladaLoader();
      loader.options.convertUpAxis = true;
      //读取模型
      loader.load( 'models/monster.dae', function ( collada ) {
        dae = collada.scene;
        dae.traverse( function ( child ) {
          if ( child instanceof THREE.SkinnedMesh ) {
            var animation = new THREE.Animation( child, child.geometry.animation );
            animation.play();
          }
        } );
        //设置模型大小
        dae.scale.x = dae.scale.y = dae.scale.z = 0.001;
        dae.position.x = dae_x;
        dae.position.y = dae_y;
        dae.position.z = -2;
        dae.rotation.y= 1 * Math.PI;
        dae.updateMatrix();
        //添加模型
        scene.add( dae );
        //环境光
        scene.add( new THREE.AmbientLight( 0xffffff ) );
      } );
}
addMonster();

模型动画播放要在animate(timestamp)中添加时钟动画

  var delta = clock.getDelta();
  // animate Collada model
  THREE.AnimationHandler.update( delta );
  mixer.update( delta );

基于pandatv的直播画面

利用plane将对应的视频进行渲染显示
对应如何直播在后面再详细介绍

//获取对应json
function getPlanesData(){
   ...
}

//生成对应的plane
function addPlane(item) {

  var img=item.pictures.img;
  //避免跨域
  img=img.replace('http:/','/u');
  var texture = new THREE.TextureLoader().load(img);
  texture.wrapS = THREE.ClampToEdgeWrapping;
  texture.wrapT = THREE.ClampToEdgeWrapping;
  var radio=1.5;
  var planeWidth=0.4*radio;
  var planeHeight=0.3*radio;
  var planeSpan=0.05*radio;
  var geometry = new THREE.PlaneGeometry(planeWidth,planeHeight);

  var material =new THREE.MeshBasicMaterial({
    map: texture,
    color: 0xffffff,
    side: THREE.BackSide
  });
  //生成对应plane,并添加到虚拟场景
  var plane = new THREE.Mesh( geometry, material);
  plane.name="plane_"+plane_position;
  plane.data=item;
  plane.position.set(1.5, controls.userHeight-0.5, 0.5);
  plane.position.y+=(plane_position%4)*(planeHeight+planeSpan);
  plane.position.z=parseInt(plane_position/4)*(planeWidth+planeSpan);
  plane_position+=1;
  plane.rotation.y=Math.PI/2;
  scene.add(plane);

  //首次添加开始播放
  if(!playing){
    playing=true;
    playRoom(item);
  }
}

视频直播

利用hls.js播放对应的链接就可以在项目中实现直播播放

  • 加载hls.js
<script src="src/hls.min.js"></script>
  • 初始化hls.js
var VRhls;
if (Hls.isSupported()) {
    //当直播开始播放时自动生成对应播放plane
    function playVideo(video){
      var texture = new THREE.VideoTexture( video );
      texture.minFilter = THREE.LinearFilter;
      texture.magFilter = THREE.LinearFilter;
      texture.format = THREE.RGBFormat;

      texture.wrapS = THREE.ClampToEdgeWrapping;
      texture.wrapT = THREE.ClampToEdgeWrapping;

      var geometry = new THREE.PlaneGeometry(3, 1.8);
      var material = new THREE.MeshBasicMaterial({
        map: texture,
        color: 0xffffff,
        side: THREE.DoubleSide
      });
      var videoPlane=new THREE.Mesh(geometry, material);
      videoPlane.position.set(0, controls.userHeight, -1.5);
      videoPlane.position.x=0;
      scene.add(videoPlane);
    }
    var video2 = document.getElementById('video2');
    //初始化
    var hls = new Hls();
    var VRhls=hls;
    hls.attachMedia(video2);
    hls.on(Hls.Events.MANIFEST_PARSED, function() {
        //当直播开始时,调用生成对应播放窗口
        playVideo(video2);
    });
}
  • 播放对应的pandatv直播 playroom(room)
function playRoom(room){
  var url="/u/room.api.m.panda.tv/index.php?method=room.shareapi&roomid="+room.id;
  $.getJSON(url,'',function(json){
    var urlVideo=json.data.videoinfo.address;
    urlVideo=urlVideo.replace('http:/','/u');
    //读取对应直播流
    VRhls.loadSource(urlVideo);
    VRhls.attachMedia(video2);
  });
}
  • nginx反向代理
    pandatv的url都是外部链接.用js调用时会出现跨域的问题.所以需要配置nginx的反向代理功能
server {
    resolver 114.114.114.114;
    ...
    location ~* ^/u/(.*)$ {
          proxy_pass http://$1?$args;
    }
}

简单交互

  • 点击事件
    点击pandatv对应列表播放直播
function animate(timestamp) {
  ...
  var intersects = raycaster.intersectObjects( scene.children );
  if(select){
    select=false;
    for ( var i = 0; i < intersects.length; i++ ) {
      var object=intersects[ i ].object;
      if(object.data){
        //点击对应的plane开始播放直播
        playRoom(object.data);
      }
    }
  }
}

结语

对应更多信息可以查看项目开源地址lhbxxx / vr-stream-web-player

QQ交流群: 241587879(验证信息:VR直播)

最新版本和技术支持可以联系:e-mail:100520140@qq.com

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值