]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blobdiff - client/src/assets/player/video-renderer.ts
(embed) sandbox the iframe
[github/Chocobozzz/PeerTube.git] / client / src / assets / player / video-renderer.ts
index bda40b11d0ceaac7dda380c1bc860679e1915273..4affb43cf1c951aa87cf23c3d246c971b83a9d7d 100644 (file)
@@ -1,8 +1,8 @@
 // Thanks: https://github.com/feross/render-media
 // TODO: use render-media once https://github.com/feross/render-media/issues/32 is fixed
 
-import { extname } from 'path'
 import * as MediaElementWrapper from 'mediasource'
+import { extname } from 'path'
 import * as videostream from 'videostream'
 
 const VIDEOSTREAM_EXTS = [
@@ -27,32 +27,49 @@ function renderVideo (
   return renderMedia(file, elem, opts, callback)
 }
 
-function renderMedia (file, elem: HTMLVideoElement, opts: RenderMediaOptions, callback: (err: Error, renderer: any) => void) {
+function renderMedia (file, elem: HTMLVideoElement, opts: RenderMediaOptions, callback: (err: Error, renderer?: any) => void) {
   const extension = extname(file.name).toLowerCase()
   let preparedElem = undefined
   let currentTime = 0
   let renderer
 
-  if (VIDEOSTREAM_EXTS.indexOf(extension) >= 0) {
-    renderer = useVideostream()
-  } else {
-    renderer = useMediaSource()
+  try {
+    if (VIDEOSTREAM_EXTS.indexOf(extension) >= 0) {
+      renderer = useVideostream()
+    } else {
+      renderer = useMediaSource()
+    }
+  } catch (err) {
+    return callback(err)
   }
 
   function useVideostream () {
     prepareElem()
-    preparedElem.addEventListener('error', fallbackToMediaSource)
+    preparedElem.addEventListener('error', function onError () {
+      preparedElem.removeEventListener('error', onError)
+
+      return fallbackToMediaSource()
+    })
     preparedElem.addEventListener('loadstart', onLoadStart)
     return videostream(file, preparedElem)
   }
 
-  function useMediaSource () {
+  function useMediaSource (useVP9 = false) {
+    const codecs = getCodec(file.name, useVP9)
+
     prepareElem()
-    preparedElem.addEventListener('error', callback)
+    preparedElem.addEventListener('error', function onError (err) {
+      preparedElem.removeEventListener('error', onError)
+
+      // Try with vp9 before returning an error
+      if (codecs.indexOf('vp8') !== -1) return fallbackToMediaSource(true)
+
+      return callback(err)
+    })
     preparedElem.addEventListener('loadstart', onLoadStart)
 
     const wrapper = new MediaElementWrapper(preparedElem)
-    const writable = wrapper.createWriteStream(getCodec(file.name))
+    const writable = wrapper.createWriteStream(codecs)
     file.createReadStream().pipe(writable)
 
     if (currentTime) preparedElem.currentTime = currentTime
@@ -60,10 +77,11 @@ function renderMedia (file, elem: HTMLVideoElement, opts: RenderMediaOptions, ca
     return wrapper
   }
 
-  function fallbackToMediaSource () {
-    preparedElem.removeEventListener('error', fallbackToMediaSource)
+  function fallbackToMediaSource (useVP9 = false) {
+    if (useVP9 === true) console.log('Falling back to media source with VP9 enabled.')
+    else console.log('Falling back to media source..')
 
-    useMediaSource()
+    useMediaSource(useVP9)
   }
 
   function prepareElem () {
@@ -96,16 +114,19 @@ function validateFile (file) {
   }
 }
 
-function getCodec (name: string) {
+function getCodec (name: string, useVP9 = false) {
   const ext = extname(name).toLowerCase()
-  return {
-    '.m4a': 'audio/mp4; codecs="mp4a.40.5"',
-    '.m4v': 'video/mp4; codecs="avc1.640029, mp4a.40.5"',
-    '.mkv': 'video/webm; codecs="avc1.640029, mp4a.40.5"',
-    '.mp3': 'audio/mpeg',
-    '.mp4': 'video/mp4; codecs="avc1.640029, mp4a.40.5"',
-    '.webm': 'video/webm; codecs="opus, vorbis, vp8"'
-  }[ext]
+  if (ext === '.mp4') {
+    return 'video/mp4; codecs="avc1.640029, mp4a.40.5"'
+  }
+
+  if (ext === '.webm') {
+    if (useVP9 === true) return 'video/webm; codecs="vp9, opus"'
+
+    return 'video/webm; codecs="vp8, vorbis"'
+  }
+
+  return undefined
 }
 
 export {