eshaz / icecast-metadata-js

Browser and NodeJS packages for playing and reading Icecast compatible streaming audio with realtime metadata updates.
155 stars 20 forks source link

"Worker is not defined" #94

Closed ikejs closed 2 years ago

ikejs commented 2 years ago

ReferenceError: Worker is not defined from node_modules/icecast-metadata-player/build/icecast-metadata-player-1.10.6.min.js (21:7898)

eshaz commented 2 years ago

I see you're using Next.js. Can you try the steps outlined in #72 to have icecast-metadata-player run fully client side? The library will not work server side, since it needs to query various browser apis when it's loaded to know how to play the stream.

eshaz commented 2 years ago

Closing this issue due to inactivity. Please let me know if you're still having trouble.

jonath92 commented 1 year ago

@eshaz I had the same issue with next.js and I read #72 but that didn't help for me with Next.js 13 (the example given in the referenced link which used next.js 11 however worked). A workaround which worked for me was using dynamic import:

import { useEffect, useState } from "react";
import { IcyMetadata } from "icecast-metadata-player";

export default function Home() {
  const [player, setPlayer] = useState<any>() as [any, any];
  const [metadata, setMetadata] = useState<string>();

  useEffect(() => {
    const loadPlayer = async () => {
      const { default: IcecastMetadataPlayer } = await import(
        "icecast-metadata-player"
      );
      setPlayer(
        new IcecastMetadataPlayer("https://dsmrad.io/stream/isics-all", {
          onMetadata: (metadata: IcyMetadata) => {
            setMetadata(metadata.StreamTitle);
          },
        })
      );
    };

    loadPlayer();
  }, []);

  return (
    <>
      <button onClick={() => player.play()}>Play</button>
      <button onClick={() => player.stop()}>Stop</button>
      <div>{metadata}</div>
    </>
  );
}

I don't understand why but without the dynamic import, it didn't work for me although it was called in useEffect. Solution based on: https://github.com/vercel/next.js/issues/33217. I am not sure yet about the downsides of this approach but for the moment i am satisfied with this.

eshaz commented 1 year ago

I think this should work ok from how I understand Next.js to work.

The problem is that Next.js attempts to execute the IcecastMetadataPlayer code server side using a NodeJS runtime environment. This can be helpful in some cases, such as prerendering some HTML elements thus avoiding some computation on the client.

However, IcecastMetadataPlayer needs to be executed fully on the client side, since it and its dependencies rely heavily on web only apis. Your dynamic import will essentially prevent Next.js from executing anything in the library because the import and IcecastMetadataPlayer is evaluated in runtime on the browser.

There might be another way to configure Next.js to not execute IcecastMetadataPlayer on the server side. I'm sure that's documented somewhere. IcecastMetadataPlayer is certainly not the only web library with this need.