zhw2590582 / ArtPlayer

:art: ArtPlayer.js is a modern and full featured HTML5 video player
https://artplayer.org
MIT License
2.49k stars 264 forks source link

使用 Media Source Extensions 播放ts无法正常加载 #695

Closed lycorisor closed 7 months ago

lycorisor commented 7 months ago

通过customType自定义播放方式

customType: {
      ts: function (video: HTMLMediaElement, url: string) {
        if (!window.MediaSource) {
          console.error("MediaSource API is not available")
          return
        }
        const mediaSource = new MediaSource()
        video.src = URL.createObjectURL(mediaSource)
        mediaSource.addEventListener("sourceopen", sourceOpen, { once: true })
        function sourceOpen() {
          const sourceBuffer = mediaSource.addSourceBuffer(
            'video/mp2t; codecs="avc1.42E01E, mp4a.40.2"',
          )
          fetch(url)
            .then(function (response) {
              if (response.body == null) {
                throw new Error("Video is not found")
              }
              return response.arrayBuffer()
            })
            .then(function (arrayBuffer) {
              sourceBuffer.addEventListener("updateend", function (_: any) {
                if (
                  !sourceBuffer.updating &&
                  mediaSource.readyState === "open"
                ) {
                  mediaSource.endOfStream()
                }
              })
              sourceBuffer.appendBuffer(
                arrayBuffer,
              )
            })
            .catch((err) => {
              console.error("Error fetching video:", err)
            })
        }
      },

播放器一直提示正在重试,开F12看了一下确实在不停重新加载视频资源文件

zhw2590582 commented 7 months ago

我这边没有ts的视频文件去测试你的代码,但我使用fmp4测试了,是可以播放的:[demo](https://artplayer.org/?libs=&code=var%20art%20%3D%20new%20Artplayer(%7B%0A%09container%3A%20%27.artplayer-app%27%2C%0A%09url%3A%20%27%2Fassets%2Fsample%2Ffrag_bunny.mp4%27%2C%0A%09customType%3A%20%7B%0A%09%09mp4%3A%20function%20(video%2C%20url)%20%7B%0A%09%09%09if%20(!window.MediaSource)%20%7B%0A%09%09%09%09console.error(%22MediaSource%20API%20is%20not%20available%22)%0A%09%09%09%09return%0A%09%09%09%7D%0A%09%09%09const%20mediaSource%20%3D%20new%20MediaSource()%0A%09%09%09video.src%20%3D%20URL.createObjectURL(mediaSource)%0A%09%09%09mediaSource.addEventListener(%22sourceopen%22%2C%20sourceOpen%2C%20%7B%20once%3A%20true%20%7D)%0A%09%09%09function%20sourceOpen()%20%7B%0A%09%09%09%09const%20sourceBuffer%20%3D%20mediaSource.addSourceBuffer(%0A%09%09%09%09%09%27video%2Fmp4%3B%20codecs%3D%22avc1.42E01E%2C%20mp4a.40.2%22%27%2C%0A%09%09%09%09)%0A%09%09%09%09fetch(url)%0A%09%09%09%09%09.then(function%20(response)%20%7B%0A%09%09%09%09%09%09if%20(response.body%20%3D%3D%20null)%20%7B%0A%09%09%09%09%09%09%09throw%20new%20Error(%22Video%20is%20not%20found%22)%0A%09%09%09%09%09%09%7D%0A%09%09%09%09%09%09return%20response.arrayBuffer()%0A%09%09%09%09%09%7D)%0A%09%09%09%09%09.then(function%20(arrayBuffer)%20%7B%0A%09%09%09%09%09%09sourceBuffer.addEventListener(%22updateend%22%2C%20function%20(_)%20%7B%0A%09%09%09%09%09%09%09if%20(%0A%09%09%09%09%09%09%09%09!sourceBuffer.updating%20%26%26%0A%09%09%09%09%09%09%09%09mediaSource.readyState%20%3D%3D%3D%20%22open%22%0A%09%09%09%09%09%09%09)%20%7B%0A%09%09%09%09%09%09%09%09mediaSource.endOfStream()%0A%09%09%09%09%09%09%09%7D%0A%09%09%09%09%09%09%7D)%0A%09%09%09%09%09%09sourceBuffer.appendBuffer(%0A%09%09%09%09%09%09%09arrayBuffer%2C%0A%09%09%09%09%09%09)%0A%09%09%09%09%09%7D)%0A%09%09%09%09%09.catch((err)%20%3D%3E%20%7B%0A%09%09%09%09%09%09console.error(%22Error%20fetching%20video%3A%22%2C%20err)%0A%09%09%09%09%09%7D)%0A%09%09%09%7D%0A%09%09%7D%2C%0A%09%7D%0A%7D)%3B)

不停重新加载视频资源文件,是因为video元素触发了error事件,可能是url失效,或者浏览器不支持解码这个文件

zhw2590582 commented 7 months ago

不过假如是ts文件的话,可以考虑用第三方库去解码,例如hls.js

lycorisor commented 7 months ago

好的,谢谢

lycorisor commented 7 months ago

我这边没有ts的视频文件去测试你的代码,但我使用fmp4测试了,是可以播放的:[demo](https://artplayer.org/?libs=&code=var%20art%20%3D%20new%20Artplayer(%7B%0A%09container%3A%20%27.artplayer-app%27%2C%0A%09url%3A%20%27%2Fassets%2Fsample%2Ffrag_bunny.mp4%27%2C%0A%09customType%3A%20%7B%0A%09%09mp4%3A%20function%20(video%2C%20url)%20%7B%0A%09%09%09if%20(!window.MediaSource)%20%7B%0A%09%09%09%09console.error(%22MediaSource%20API%20is%20not%20available%22)%0A%09%09%09%09return%0A%09%09%09%7D%0A%09%09%09const%20mediaSource%20%3D%20new%20MediaSource()%0A%09%09%09video.src%20%3D%20URL.createObjectURL(mediaSource)%0A%09%09%09mediaSource.addEventListener(%22sourceopen%22%2C%20sourceOpen%2C%20%7B%20once%3A%20true%20%7D)%0A%09%09%09function%20sourceOpen()%20%7B%0A%09%09%09%09const%20sourceBuffer%20%3D%20mediaSource.addSourceBuffer(%0A%09%09%09%09%09%27video%2Fmp4%3B%20codecs%3D%22avc1.42E01E%2C%20mp4a.40.2%22%27%2C%0A%09%09%09%09)%0A%09%09%09%09fetch(url)%0A%09%09%09%09%09.then(function%20(response)%20%7B%0A%09%09%09%09%09%09if%20(response.body%20%3D%3D%20null)%20%7B%0A%09%09%09%09%09%09%09throw%20new%20Error(%22Video%20is%20not%20found%22)%0A%09%09%09%09%09%09%7D%0A%09%09%09%09%09%09return%20response.arrayBuffer()%0A%09%09%09%09%09%7D)%0A%09%09%09%09%09.then(function%20(arrayBuffer)%20%7B%0A%09%09%09%09%09%09sourceBuffer.addEventListener(%22updateend%22%2C%20function%20(_)%20%7B%0A%09%09%09%09%09%09%09if%20(%0A%09%09%09%09%09%09%09%09!sourceBuffer.updating%20%26%26%0A%09%09%09%09%09%09%09%09mediaSource.readyState%20%3D%3D%3D%20%22open%22%0A%09%09%09%09%09%09%09)%20%7B%0A%09%09%09%09%09%09%09%09mediaSource.endOfStream()%0A%09%09%09%09%09%09%09%7D%0A%09%09%09%09%09%09%7D)%0A%09%09%09%09%09%09sourceBuffer.appendBuffer(%0A%09%09%09%09%09%09%09arrayBuffer%2C%0A%09%09%09%09%09%09)%0A%09%09%09%09%09%7D)%0A%09%09%09%09%09.catch((err)%20%3D%3E%20%7B%0A%09%09%09%09%09%09console.error(%22Error%20fetching%20video%3A%22%2C%20err)%0A%09%09%09%09%09%7D)%0A%09%09%09%7D%0A%09%09%7D%2C%0A%09%7D%0A%7D)%3B)

不停重新加载视频资源文件,是因为video元素触发了error事件,可能是url失效,或者浏览器不支持解码这个文件

后面看了一下确实是编码的问题,我把你这个测试视频拿过来就可以播放