これは何?
今まで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 すれば動きます。