shiyiya / oplayer

:zap: Another HTM5 video player.
https://oplayer.vercel.app
MIT License
147 stars 19 forks source link

Play Separated Video & Audio Files #78

Closed namdevel closed 1 year ago

namdevel commented 1 year ago

hello, how to play separated video and audio files

example i have 2 file

  1. video without audio sound
  2. audio sound of video
shiyiya commented 1 year ago

@namdevel

You can try this, but why not use ffmpeg to merge them?

class SeparatedAudio implements PlayerPlugin {
  key = 'hello'
  name = 'oplayer-plugin-hello'
  version = __VERSION__

  private $audio: HTMLAudioElement = document.createElement('audio')

  constructor(private audioSrc: string) {
    this.$audio.src = this.audioSrc
  }

  apply(player: Player) {
    player.on(['play', 'pause'], ({ type }) => {
      //@ts-ignore
      this.$audio[type]()
      this.$audio.currentTime = player.currentTime
    })

    player.on(['seeking', 'error'], () => {
      this.$audio.pause()
    })

    const loading = $.cls('loading')
    player.on(() => {
      if (player.$root.classList.contains(loading)) {
        this.$audio.pause()
      } else {
        if (player.isPlaying && this.$audio.paused) {
          this.$audio.play()
        }
      }
    })

    player.on('seeked', () => {
      this.$audio.currentTime = player.currentTime
      if (player.isPlaying) this.$audio.play()
    })

    player.on('volumechange', () => {
      this.$audio.volume = player.volume
    })

    player.on('ratechange', () => {
      this.$audio.playbackRate = player.playbackRate
    })
    // .... other
  }

  destroy() {
    this.$audio.remove()
    URL.revokeObjectURL(this.$audio.src)
  }
}
namdevel commented 1 year ago

@shiyiya because the audio and video hosted in separate files

namdevel commented 1 year ago

@shiyiya and why i seeing this, player.context.ui.menu.notice is not a function

shiyiya commented 1 year ago

@shiyiya and why i seeing this, player.context.ui.menu.notice is not a function

use latest version @oplayer/core @oplayer/ui

namdevel commented 1 year ago

yes, here is my code

<div id="oplayer"></div>
<script src="https://cdn.jsdelivr.net/npm/@oplayer/core@latest/dist/index.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@oplayer/ui@latest/dist/index.core.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@oplayer/core@latest/dist/index.ui.js"></script>

<script>
  const audio = new Audio("https://ngewibu.test/stream/audio/1/12771946.mp4");
  audio.load();
  const UIPlayer = OPlayer.ui({
    fullscreen: true,
    coverButton: true,
    miniProgressBar: true,
    autoFocus: true,
    forceLandscapeOnFullscreen: true,
    screenshot: true,
    pictureInPicture: false,
    showControls: "always",
    keyboard: { focused: true, global: false },
    settings: ["loop"],
    theme: { primaryColor: "#ffc107" },
    speeds: ["2.0", "1.75", "1.25", "1.0", "0.75", "0.5"],
    slideToSeek: "none",
    controlBar: false, // | { back:  'always' | 'fullscreen' } // appbar
    topSetting: false, //show setting icon on appbar
    /* Default value, Optional */

    /* Custom options */
    subtitle: {
      color: "white",
      fontSize: 30,
      fontFamily: "",
      source: [
        {
          name: "Bahasa Indonesia",
          default: true,
          src: "sub.vtt",
        },
      ],
    },
    thumbnails: {
      number: 100,
      src: "https://oplayer.vercel.app/thumbnails.jpg",
    },
  });

  const vplayer = OPlayer.make("#oplayer", {
    source: {
      src: "https://ngewibu.test/stream/videos/1/12771946.mp4",
      poster:
        "https://ngewibu.test/static/img/ogv/5d04814e48ef572e97cb18bbe928bbf8086c38cf.png@720w_405h_1e_1c_90q.webp",
      title: "Ngewibu.test",
    },
  }).use([UIPlayer]);
  vplayer.create();
  vplayer.context.ui.menu.notice("test hello"); // test notice
</script>
<script>
  function playMedia() {
    audio.play();
  }

  function pauseMedia() {
    audio.pause();
  }
  function seekMedia() {
    audio.currentTime = vplayer.currentTime;
  }
  // Keep audio and video in sync
  function syncMedia() {
    audio.currentTime = vplayer.currentTime;
  }

  // Event listeners
  vplayer.on("play", playMedia);
  vplayer.on("durationchange", syncMedia);
  vplayer.on("pause", pauseMedia);
  vplayer.on("seeked", seekMedia);
</script>
shiyiya commented 1 year ago

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="oplayer"></div>
    <script src="https://cdn.jsdelivr.net/npm/@oplayer/core@latest/dist/index.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/@oplayer/ui@latest/dist/index.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/@oplayer/hls@latest/dist/index.hls.js"></script>

    <script>
      class SeparatedAudio {
        constructor(audioSrc) {
          this.audioSrc = audioSrc
          this.key = 'hello'
          this.name = 'oplayer-plugin-hello'
          this.$audio = document.createElement('audio')
          this.$audio.src = this.audioSrc
        }
        apply(player) {
          player.on(['play', 'pause'], ({ type }) => {
            this.$audio[type]()
            this.$audio.currentTime = player.currentTime
          })
          player.on(['seeking', 'error'], () => {
            this.$audio.pause()
          })
          const loading = OPlayer.$.cls('loading')
          player.on(() => {
            if (player.$root.classList.contains(loading)) {
              this.$audio.pause()
            } else {
              if (player.isPlaying && this.$audio.paused) {
                this.$audio.play()
              }
            }
          })
          player.on('seeked', () => {
            this.$audio.currentTime = player.currentTime
            if (player.isPlaying) this.$audio.play()
          })
          player.on('volumechange', () => {
            this.$audio.volume = player.volume
          })
          player.on('ratechange', () => {
            this.$audio.playbackRate = player.playbackRate
          })
          // .... other
        }
        destroy() {
          this.$audio.remove()
          URL.revokeObjectURL(this.$audio.src)
        }
      }

      const UI = OUI({
        fullscreen: true,
        coverButton: true,
        miniProgressBar: true,
        autoFocus: true,
        forceLandscapeOnFullscreen: true,
        screenshot: true,
        pictureInPicture: false,
        showControls: 'always',
        keyboard: { focused: true, global: false },
        settings: ['loop'],
        theme: { primaryColor: '#ffc107' },
        speeds: ['2.0', '1.75', '1.25', '1.0', '0.75', '0.5'],
        slideToSeek: 'none',
        controlBar: false, // | { back:  'always' | 'fullscreen' } // appbar
        topSetting: false, //show setting icon on appbar
        /* Default value, Optional */

        /* Custom options */
        subtitle: {
          color: 'white',
          fontSize: 30,
          fontFamily: '',
          source: [
            {
              name: 'Bahasa Indonesia',
              default: true,
              src: 'sub.vtt',
            },
          ],
        },
        thumbnails: {
          number: 100,
          src: 'https://oplayer.vercel.app/thumbnails.jpg',
        },
      })

      const vplayer = OPlayer.make('#oplayer', {
        source: {
          src: 'https://ngewibu.test/stream/videos/1/12771946.mp4',
          poster: 'https://ngewibu.test/static/img/ogv/5d04814e48ef572e97cb18bbe928bbf8086c38cf.png@720w_405h_1e_1c_90q.webp',
          title: 'Ngewibu.test',
        },
      })
        .use([UI, new SeparatedAudio('https://ngewibu.test/stream/audio/1/12771946.mp4')])
        .create()

      vplayer.context.ui.notice('test hello') // test notice
    </script>
  </body>
</html>
namdevel commented 1 year ago

thank you @shiyiya can this player add watermark image ? like in top left or whenever custom position ?

shiyiya commented 1 year ago

thank you @shiyiya can this player add watermark image ? like in top left or whenever custom position ?


document.createlm(img)
img.src =''
img.style.position= ''
vplayer.$root.appendChild(img)
namdevel commented 1 year ago

thank you

var img = document.createElement("img");
img.src = "layer.png";
img.style.position = "absolute";
img.style.top = "10px";
img.style.right = "10px";
img.style.width = "200px";
img.style.height = "auto";
vplayer.$root.appendChild(img);
namdevel commented 1 year ago

i hope you can add watermark in Oplayer options in future I wanted to take a moment to express my sincerest thanks for your incredible work.

shiyiya commented 1 year ago

i hope you can add watermark in Oplayer options in future I wanted to take a moment to express my sincerest thanks for your incredible work.

I will consider it, thank u 😄

namdevel commented 1 year ago

Screenshot_76

i'm seeing this error while take a screenshot

shiyiya commented 1 year ago

Screenshot_76

i'm seeing this error while take a screenshot

https://github.com/shiyiya/oplayer/blob/b86db76707fd61d66454913ffa0ccd009fa0763c/examples/standalone/main.ts#L51

namdevel commented 1 year ago

how to add custom slide in settings menu ? like loop menu but custom and handle on off

shiyiya commented 1 year ago

how to add custom slide in settings menu ? like loop menu but custom and handle on off

https://github.com/shiyiya/oplayer/blob/b86db76707fd61d66454913ffa0ccd009fa0763c/packages/ui/src/functions/speed.ts#L14

namdevel commented 1 year ago

i'm confused ^_^

shiyiya commented 1 year ago
player.context.ui.setting.register()
namdevel commented 1 year ago

tester.html:117 Uncaught TypeError: Cannot read properties of undefined (reading 'setting')

namdevel commented 1 year ago

oh sorry my mistakes

namdevel commented 1 year ago

Screenshot_77

become default controls in mobile views/device

shiyiya commented 1 year ago

The real machine is not the same as the fake

截图_77

namdevel commented 1 year ago

i try in my real iOS device and it's same , that was appeared while in the fullscreen mode

shiyiya commented 1 year ago

i try in my real iOS device and it's same , that was appeared while in the fullscreen mode

Yes, this is normal, ios can only video in full screen

namdevel commented 1 year ago

AAh ok, thank you

namdevel commented 1 year ago

WhatsApp Image 2023-05-20 at 20 17 34

while i try use another video player, they can show custom controls in my Device

shiyiya commented 1 year ago

WhatsApp Image 2023-05-20 at 20 17 34

while i try use another video player, they can show custom controls in my Device

try npm i oplayer/core@1.2.26-beta.1

namdevel commented 1 year ago

is that available on jsdeliver version ? because i'm not use npm

shiyiya commented 1 year ago
<script src="https://cdn.jsdelivr.net/npm/@oplayer/core@latest/dist/index.min.js"></script>

replace

namdevel commented 1 year ago

how to add multiple thumbnails

image 1 image 2

x : 10 y: 10

x_sizes: 160 y_sizes: 90

shiyiya commented 1 year ago

how to add multiple thumbnails

image 1 image 2

x : 10 y: 10

x_sizes: 160 y_sizes: 90

https://oplayer.vercel.app/ui/#thumbnails default size is 160 90,

thumbnails = {
  src: ['image1','image2'],
  x: 10,
  y: 6,
  number: 60
}
namdevel commented 1 year ago

not work, the thumbnails not same with video time

shiyiya commented 1 year ago

not work, the thumbnails not same with video time

Can you provide an example?

namdevel commented 1 year ago

https://i0.hdslb.com/bfs/videoshot/n230403er32xsq8sww4izs2q666shb65.jpg https://i0.hdslb.com/bfs/videoshot/n230403er32xsq8sww4izs2q666shb65-1.jpg

shiyiya commented 1 year ago

403 If you can provide accessible videos and pictures, I can try to fix the error tomorrow

namdevel commented 1 year ago

forbidden access from videoplayer or from url ?

shiyiya commented 1 year ago

yea

forbidden access from videoplayer or from url ?

shiyiya commented 1 year ago

not work, the thumbnails not same with video time

Of course, it is possible that the number of thumbnails generated is small and the gaps are too large so they are not that accurate

namdevel commented 1 year ago

thumb thumb-1

video duration is 24:00 minutes

shiyiya commented 1 year ago

video duration is 24:00 minutes

thumbnails = { src: ['image1','image2'], x: 10, y: 10, number: 192 }

shiyiya commented 1 year ago

Can you provide a complete example, fork template, add video address and thumbnails configuration https://codesandbox.io/s/oplayer-m4inym

namdevel commented 1 year ago

Screenshot_78

i'ts normal ?

shiyiya commented 1 year ago

I'm not sure if it's normal, it depends on the number of thumbnails you generate, for example, if the video is 10 minutes long and 2 thumbnails are generated, then it's quite inaccurate. If your video is 24 minutes long and there are only 200 thumbnails, then the error of one thumbnail is 24*60/200=13.xxs. As long as the image exists before or after 13s of the video, it means it is normal.

namdevel commented 1 year ago

Screenshot_79 but on bilibili that was same, and in bilibili website player it seem like your player

shiyiya commented 1 year ago

OK, it is certain that it should be an issue with oplayer. But to fix it you need to provide videos and thumbnails 😂

Can you provide a complete example, fork template, add video address and thumbnails configuration https://codesandbox.io/s/oplayer-m4inym

namdevel commented 1 year ago

i has been add

namdevel commented 1 year ago

hmm how to save code that i has been modified ?

shiyiya commented 1 year ago

hmm how to save code that i has been modified ?

just ctrl+s and then share the link to me in the top right corner, or just copy the link in the address bar?

namdevel commented 1 year ago

https://4r7q6f.csb.app/

shiyiya commented 1 year ago

https://4r7q6f.csb.app/

Not this one, but a link like codesanbox.io/xxxx

OK, this is also possible

namdevel commented 1 year ago

you can click open sandbox in bottom right

https://codesandbox.io/s/4r7q6f