SRGSSR / pillarbox-web

Pillarbox is a versatile media playback ecosystem engineered for the web.
https://srgssr.github.io/pillarbox-web-demo/
MIT License
12 stars 1 forks source link

The contrib-eme plugin does not load correctly #222

Open amtins opened 7 months ago

amtins commented 7 months ago

Description

When a react application is created with vite, the videojs-contrib-eme plugin does not seem to load correctly.

How to reproduce

import { useEffect } from "react";

type playerSrc = { urn: string };

declare global { interface Window { pillarbox: typeof Pillarbox; } }

export function Pbw({ urn }: playerSrc) {

useEffect(() => { window.pillarbox = Pillarbox;

const player = Pillarbox('player');

player.src({ src: urn, type: 'srgssr/urn' })

}, [urn]);

return (

) }

- update the App.tsx file with the code below
```javascript
import './App.css'
import { Pbw } from './pbw'

function App() {

  return (
    <>
      <h1>Pillarbox + React</h1>
      <div className="card">
        <Pbw urn="urn:srf:video:c71b3914-128e-4844-a5e3-589bd99469b1"></Pbw>
      </div>
    </>
  )
}

export default App

Hints

amtins commented 7 months ago

@wetteyve just to let you know that I was unable to reproduce the problem with npm. However, it is easily reproducible with yarn.

Steps to reproduce

My yarn environment is very sketchy...

Hints

yarn v1.22.19

Screenshot from 2024-03-08 17-28-33

amtins commented 7 months ago

Side note, to fix the yarn permission issue : yarn config set prefix ~/.local

wetteyve commented 6 months ago

Side note, to fix the yarn permission issue : yarn config set prefix ~/.local

on play web (using yarn v3.3.1) seting the "prefix" config produces an error: image

amtins commented 6 months ago

@wetteyve I went old school with the version of yarn I already had installed on my machine, and apparently I was forced to use sudo for all commands. So the comment was only intended to fix my sudo problem and not the main issue. 🥲

amtins commented 6 months ago

@wetteyve I have a workaround that lets you use the player while waiting for the fix. It's a bit ugly and there is no type hinting, but it works.

import '../node_modules/@srgssr/pillarbox-web/dist/pillarbox.umd.js';

// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
const player = Pillarbox('player');
jboix commented 6 months ago

@wetteyve For some reason it seems that yarn cannot deduplicate the videojs-contrib-eme version and is installing multiple instances of this module. We might have to move the declaration of video-js and videojs-contrib-eme as peerDependencies.

In the meantime you can use @amtins workaround or point yarn to the good version by adding this to the package.json:

"resolutions": {
    "video.js": "8.11.1",
    "videojs-contrib-eme": "3.11.2"
}

I have a working example here: https://github.com/jboix/yarn-pillarbox You can see the resolution here: https://github.com/jboix/yarn-pillarbox/blob/main/package.json#L27

wetteyve commented 6 months ago

@jboix thanks for the update, i continue my work by adding the resolutions for now 👍

jboix commented 6 months ago

After further investigation this is what I found.


Overview

Using yarn, the project ends up with both 8.10.0 and 8.11.8 versions of video.js installed, contrary to the npm behavior, which deduplicates to a single version, 8.11.8, avoiding such issues.

Specific Issues

The core of the problem lies in two cyclic dependencies involving video.js:

  1. video.js -> @videojs/http-streaming -> video.js
  2. video.js -> videojs-contrib-quality-level -> video.js

Both cyclic dependencies are problematic, but the first one is particularly troubling because it involves both a peerDependency and a dependency on video.js, specified in the package.json of the latest version as follows:

Example

See here a minimal yarn project demonstrating the issue: jboix/vjs-yarn. Upon inspecting the project in a browser, it becomes evident that two distinct versions of video.js are loaded, as showcased below:

image

One critical side effect of this results in the eme plugin loading within a single instance of the videojs, rendering it inaccessible to the other one:

mport videojs from "video.js";
import 'videojs-contrib-eme';

// This line fails
console.log(videojs.getPlugin('eme').VERSION);

The error:

image

Proposed Solutions

  1. Move video.js to a peerDependency in both videojs/videojs-contrib-quality-levels and videojs/http-streaming should prevent multiple versions from being installed and allow developers to explicitly manage the video.js version.

  2. Break the dependency cycle by moving the shared logic to videojs/vhs-utils.

  3. Break the dependency cycle by introducing a new package, e.g.:

    • Create videojs-bundle that includes: video.js, @videojs/http-streaming and videojs/videojs-contrib-quality-levels.
    • Remove @videojs/http-streaming and videojs/videojs-contrib-quality-levels from video.js.

Workaround

When integrating the project with yarn force the version resolution by adding this to the package.json:

"resolutions": {
    "video.js": "8.11.8"
}