LoginSignup
6
7

More than 5 years have passed since last update.

WebRTCでも360ライブストリーミングがしたい!

Posted at

これは何?

今まで360カメラなんて全く興味がなかったのに、Ricoh R developmentkit を5月末にポチってしまい、6月にすぐに発送されたのでWebRTCでライブストリーミングしてみました。

こちらのサイト様で後悔しているコードをmediasoupに組み込んで動いたよーという話です。
https://ics.media/entry/14490/3

仕組み

Ricoh R development kit と macを接続しmediasoupに流し込みます。
別端末からビューワーを開くと WebRTCのvideoタグをthree.jsで球体に貼り付けます。
それだけです。theta sよりも簡単です。

theta sとの違い

theta s のサンプルが世の中に出回っていまして、ラズパイと接続してとかできたんですが、theta sは未加工のレンズのママの映像が取得できます。
対してRicoh Rは一般的な?形式にしてくれるので球体にそのままマッピングするだけです。

ソースコード

ほとんどこちらのソースコードそのままです。
https://ics.media/entry/14490/3

WebRTC側、pc.onaddstream(stream) などでvideoタグにsrcObjectをセットする際に使います。
以下はmediasoup-demoでのファイル名と修正箇所を示しています。

three.jsをnpm installしましょう

npm install three-js --save

app/lib/components/Video.jsx

import * as sphere from './sphere';
...

video.srcObject = stream;
sphere.setVR(video); // これを追加
...

app/lib/components/sphere.js (新規作成)

import THREELib from 'three-js';

// windowサイズを画面サイズに合わせる
let width, height;
let element;
let scene, camera, renderer, controls, texture;
let THREE = THREELib(['OrbitControls']);

export function setVR(target) {
    width = 1920; // target.videoWidth;
    height = 1080; // target.videoHeight;

    // シーンの作成
    scene = new THREE.Scene();

    // リサイズイベントを検知してリサイズ処理を実行
    window.addEventListener('resize', handleResize, false);

    // カメラの作成
    camera = new THREE.PerspectiveCamera(75, width / height, 1, 1000);
    camera.position.set(0, 0, 0.1);
    scene.add(camera);

    // 球体の形状を作成
    var geometry = new THREE.SphereGeometry(5, 60, 40);
    geometry.scale(-1, 1, 1);

    // テクスチャーにvideoを設定
    texture = new THREE.VideoTexture(target);
    texture.minFilter = THREE.LinearFilter;
    texture.magFilter = THREE.LinearFilter;
    texture.format = THREE.RGBFormat;

    // マテリアルの作成
    var material = new THREE.MeshBasicMaterial({
      // 画像をテクスチャとして読み込み
      map: texture
    });

    // 球体(形状)にマテリアル(質感)を貼り付けて物体を作成
    let sphere = new THREE.Mesh(geometry, material);

    // シーンに追加
    scene.add(sphere);

    // レンダラーの作成
    renderer = new THREE.WebGLRenderer({antialias: true});
    // レンダラーをwindowサイズに合わせる
    renderer.setSize(window.innerWidth, window.innerHeight);
    renderer.setClearColor({color: 0xffccff});
    element = renderer.domElement;
    target.parentNode.appendChild(element);
    renderer.render(scene, camera);

    // デバイスの判別
    var isAndroid = false;
    var isIOS = false;
    if (navigator.userAgent.indexOf('Android') != -1) {
      // デバイスがAndroidの場合
      isAndroid = true;
    } else if (/(iPad|iPhone|iPod)/g.test(navigator.userAgent)) {
      // デバイスがiOSの場合
      isIOS = true;
    }
    if (isAndroid || isIOS) {
      // デバイスがスマートフォンまたはタブレット端末の場合
      // ジャイロセンサーで視点操作を可能にする
    } else {
      // パソコンの場合
      // マウスドラッグで視点操作を可能にする
      setOrbitControls();
    }

    render();
  }

  // リサイズ処理
  function handleResize() {
    renderer.setSize(window.innerWidth, window.innerHeight);
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
  }

  function setOrbitControls() {
    // パソコン閲覧時マウスドラッグで視点操作する
    controls = new THREE.OrbitControls(camera, element);
    controls.target.set(
      camera.position.x + 0.15,
      camera.position.y,
      camera.position.z
    );
    // 視点操作のイージングをONにする
    controls.enableDamping = true;
    // 視点操作のイージングの値
    controls.dampingFactor = 0.2;
    // 視点変更の速さ
    controls.rotateSpeed = 0.1;
    // ズーム禁止
    controls.noZoom = true;
    // パン操作禁止
    controls.noPan = true;
  }

  function render() {
    requestAnimationFrame(render);
    renderer.render(scene, camera);
    controls.update();
  }

あとは gulp prod すれば動きます。

6
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
7