# Youtube video texture \*without\* CSS3DRenderer

**URL:** <https://forum.babylonjs.com/t/youtube-video-texture-without-css3drenderer/35283>\
**Category:** Questions\
**Created:** [October 31, 2022, 1:44pm UTC](https://forum.babylonjs.com/t/youtube-video-texture-without-css3drenderer/35283 "2022-10-31T13:44:49Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![Jo\_Mantelers](https://avatars.discourse-cdn.com/v4/letter/j/b4bc9f/32.png) [@Jo\_Mantelers](https://forum.babylonjs.com/u/Jo_Mantelers)\
**Post date:** [October 31, 2022, 1:44pm UTC](https://forum.babylonjs.com/t/youtube-video-texture-without-css3drenderer/35283/1 "2022-10-31T13:44:49Z")

</div>

Not specifically babylon question but related and probably of interest to many :

Is it possible to get the MP4 stream of a Youtube video and use this as video texture in Babylon? I have seen several CSS3DRenderer based examples but like to stay away from this as I have a rather complex scene. Any suggestions?

Via Google API (need app key etc) I can get the metadata of a YT video (made a node server API endpoint for this, using the YT video ID). This provides me with a long json with several ‘formats’ and the actual mp4 stream URLs, like this one:

[https://rr5---sn-gqn-vu2e7.googlevideo.com/videoplayback?expire=1667253227&ei=i](https://rr5---sn-gqn-vu2e7.googlevideo.com/videoplayback?expire=1667253227&ei=i)…

But when assigning to a video texture, I get a CORS error:

`Access to video at 'https://rr5---sn-gqn-vu2e7.googlevideo.com/videoplayback?expire=1667253227&ei=i.....' from origin 'https://...my domain ..' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.`

However, I can open this link directly in the browser and see/hear all fine.

Does babylon have a CORS setting that I missed?

Thanks !

---

<div class="post-metadata">

**Author:** ![JohnK](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/johnk/32/26764_2.png) [@JohnK](https://forum.babylonjs.com/u/JohnK)\
**Post date:** [October 31, 2022, 4:25pm UTC](https://forum.babylonjs.com/t/youtube-video-texture-without-css3drenderer/35283/2 "2022-10-31T16:25:54Z")

</div>

> [@Jo\_Mantelers](#):
>
> But these result in CORS error although I can open the link in the browser directly

> **[Using External Assets In the Playground | Babylon.js Documentation](https://doc.babylonjs.com/toolsAndResources/thePlayground/externalPGAssets)**
>
> Learn how to use external assets in the playground in Babylon.js.

---

<div class="post-metadata">

**Author:** ![Jo\_Mantelers](https://avatars.discourse-cdn.com/v4/letter/j/b4bc9f/32.png) [@Jo\_Mantelers](https://forum.babylonjs.com/u/Jo_Mantelers)\
**Post date:** [October 31, 2022, 4:47pm UTC](https://forum.babylonjs.com/t/youtube-video-texture-without-css3drenderer/35283/3 "2022-10-31T16:47:36Z")

</div>

Thanks but I am trying to stream a video from Youtube, so cannot treat this as an asset, unfortunately.

Maybe stream via node proxy to babylon client? Ugh

---

<div class="post-metadata">

**Author:** ![sebavan](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/sebavan/32/57_2.png) [@sebavan](https://forum.babylonjs.com/u/sebavan)\
**Post date:** [October 31, 2022, 5:42pm UTC](https://forum.babylonjs.com/t/youtube-video-texture-without-css3drenderer/35283/4 "2022-10-31T17:42:20Z")

</div>

No browser (without security restrictions removed) would let you do this at the moment. The proxy server could work but you should be careful with the risk involved and the egress cost of transferring so much data 🙂

---

<div class="post-metadata">

**Author:** ![Jo\_Mantelers](https://avatars.discourse-cdn.com/v4/letter/j/b4bc9f/32.png) [@Jo\_Mantelers](https://forum.babylonjs.com/u/Jo_Mantelers)\
**Post date:** [October 31, 2022, 10:23pm UTC](https://forum.babylonjs.com/t/youtube-video-texture-without-css3drenderer/35283/5 "2022-10-31T22:23:57Z")

</div>

I found a way that seems to perform pretty ok. AND NO CORS ISSUES!

1. make a node express server with this logic:

```auto
app.use(function(req, res, next) {
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
  next();
});

app.use('/api/ytstream', async (req, res) => {
  let url = await controller.getYoutubeStreamURL(req.query.video)
  req.pipe(request(url)).pipe(res);  
});

```

1. create a controller which fetches the URL of a video by its ID:

```auto
const YT_API_KEY = '<your key>'
const YT_API_URL = 'https://youtubei.googleapis.com/youtubei/v1/player?key=' + YT_API_KEY;
const YT_API_PAYLOAD = 
`
{
  "context": {
    "client": {
     "hl": "en",
     "clientName": "WEB",
     "clientVersion": "2.20210721.00.00",
     "mainAppWebInfo": {
         "graftUrl": "/watch?v= __VIDEO_ID__"
     }
    }
   },
   "videoId": " __VIDEO_ID__"
 }  
`

exports.getYoutubeStreamURL = async (videoId) => {
  const payload = YT_API_PAYLOAD.replace(/ __VIDEO_ID__ /g, videoId)
  let raw = await fetch(YT_API_URL, {
    method: 'POST',
    body: payload,
  })

  let json = await raw.json();
  if(!json.streamingData) {
    return false;
  }
  // live stream has 'hlsManifestUrl' which is a *.m3u8 URL
  if(json.streamingData.hlsManifestUrl) {
    return json.streamingData.hlsManifestUrl;
  }
  // normal video: find largest resolution for now
  var maxh = 0;
  var useStream;
  json.streamingData.formats.forEach((stream) => {
    if (stream.height > maxh) {
      maxh = stream.height;
      useStream = stream;
    }
  })
  return useStream ? useStream.url : false;
}

```

1. load as video texture:  
const url = ‘[http://localhost:3000/api/ytstream?video=](http://localhost:3000/api/ytstream?video=)’ + videoId;  
const tex = new BABYLON.VideoTexture(“myvideo”, url , … etc)

Sweet !

TODO: how do I handle m3u8 URLs from Youtube LIVE streams ?

---

<div class="post-metadata">

**Author:** ![labris](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/labris/32/12576_2.png) [@labris](https://forum.babylonjs.com/u/labris)\
**Post date:** [November 1, 2022, 1:10am UTC](https://forum.babylonjs.com/t/youtube-video-texture-without-css3drenderer/35283/6 "2022-11-01T01:10:58Z")

</div>

> [@Jo\_Mantelers](#):
>
> TODO: how do I handle m3u8 URLs from Youtube LIVE streams ?

You may do it with [GitHub - video-dev/hls.js: HLS.js is a JavaScript library that plays HLS in browsers with support for MSE.](https://github.com/video-dev/hls.js/)  
There are some Playground examples with implementations.

---

<div class="post-metadata">

**Author:** ![Jo\_Mantelers](https://avatars.discourse-cdn.com/v4/letter/j/b4bc9f/32.png) [@Jo\_Mantelers](https://forum.babylonjs.com/u/Jo_Mantelers)\
**Post date:** [November 14, 2022, 10:05am UTC](https://forum.babylonjs.com/t/youtube-video-texture-without-css3drenderer/35283/7 "2022-11-14T10:05:38Z")

</div>

to close this question: HLS.js works fine.just find the m3u8 stream url from youtube and create a video player with hls. all rest is same as normal video texture, incl html5 media/video events like metadataloaded, canplay, etc.

---

<div class="post-metadata">

**Author:** ![RohitMallah](https://avatars.discourse-cdn.com/v4/letter/r/5daacb/32.png) [@RohitMallah](https://forum.babylonjs.com/u/RohitMallah)\
**Post date:** [December 9, 2022, 1:56pm UTC](https://forum.babylonjs.com/t/youtube-video-texture-without-css3drenderer/35283/8 "2022-12-09T13:56:51Z")

</div>

Do we have working solution for this ?

---

<div class="post-metadata">

**Author:** ![sebavan](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/sebavan/32/57_2.png) [@sebavan](https://forum.babylonjs.com/u/sebavan)\
**Post date:** [December 12, 2022, 4:49pm UTC](https://forum.babylonjs.com/t/youtube-video-texture-without-css3drenderer/35283/9 "2022-12-12T16:49:20Z")

</div>

@labris and @Jo_Mantelers answers looks like the way to go.

---

<div class="post-metadata">

**Author:** ![labris](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/labris/32/12576_2.png) [@labris](https://forum.babylonjs.com/u/labris)\
**Post date:** [December 12, 2022, 5:26pm UTC](https://forum.babylonjs.com/t/youtube-video-texture-without-css3drenderer/35283/10 "2022-12-12T17:26:41Z")

</div>

Some PG examples

- with HLS [https://playground.babylonjs.com/#9FSDC7#235](https://playground.babylonjs.com/#9FSDC7#235)
- with DASH - [https://playground.babylonjs.com/#9FSDC7#234](https://playground.babylonjs.com/#9FSDC7#234)
