Giter Club home page Giter Club logo

Comments (11)

W3AXL avatar W3AXL commented on August 16, 2024 1

Perfect, thanks for the link!

I did basically exactly what you did, minus the flac buffering, and it seems to be working pretty darn well. A little bit of skipping/crackling here or there, so I might add a half-second buffer or so, but otherwise the Metadata is perfectly sync-ed up!

from icecast-metadata-js.

eshaz avatar eshaz commented on August 16, 2024 1

@W3AXL I just released the off-the-shelf module that you can include as a <script> tag in your HTML. I also added a few new demo pages that use regular HTML and give examples on how to use the new module.
https://github.com/eshaz/icecast-metadata-js/tree/master/src/icecast-metadata-player

Since you're using this for a radio application, you may be interested in the metadata queue, which shows all of the buffered metadata updates. Usually for a low bitrate mp3 stream for P25 radio, the normal 32KB burst-size will give about 30 seconds of buffered audio / metadata. On your Icecast server, you can increase the burst-size to send more data to clients to increase the number of messages that show up in the queue.

from icecast-metadata-js.

W3AXL avatar W3AXL commented on August 16, 2024

Likely relevant to #34 as well

from icecast-metadata-js.

eshaz avatar eshaz commented on August 16, 2024

#34 will provide a separate module that can be used easily in vanilla javascript, which I believe is what you are attempting.

Referencing the library itself in the html via a script tag can certainly be done, but you would need to combine all of the other imports together and wrap the IcecastMetadataReader file in additional code so it's accessible in your html.

You could also create an npm project, install icecast-metadata-js using npm (https://github.com/eshaz/icecast-metadata-js/tree/master/src/icecast-metadata-js#installing), and then build your Javascript code with something like webpack: https://webpack.js.org. You would then use the output of the webpack build as the file to include in your HTML. I would highly recommend taking this route over manually combining the files together.

from icecast-metadata-js.

W3AXL avatar W3AXL commented on August 16, 2024

I'll give webpack a shot. #34 will probably be my best bet for a dead-simple player webapp, but in the meantime I'll see what I can do with a bundled-up version created via webpack.

Apologies for any misunderstandings, I'm still a novice when it comes to anything more advanced than basic javascript.

from icecast-metadata-js.

W3AXL avatar W3AXL commented on August 16, 2024

Currently either I'm doing something wrong, or webpack-ing the code doesn't seem to work currently.

I created an extremely basic test script using IcecastReadableStream:

import IcecastReadableStream from "icecast-metadata-js";

const endpointUrl = "https://streams.w3axl.com/icy/laportecounty";

var startButton = document.getElementById('startStream');
startButton.addEventListener('click', startStreaming);

function startStreaming() {
    console.log("beginning stream fetch");
    fetch(endpointUrl, {
        method: "GET",
        headers: {
            "Icy-MetaData": "1",
        }
    })
    .then(async (response) => {
        const icecast = new IcecastReadableStream(
            response,
            {
                parseStream,
                parseMetadata,
                metadataTypes: ["icy"]
            }
        );
        await icecast.startReading();
    })
}

function parseStream(stream) {
    //console.log(stream);
}

function parseMetadata(metadata) {
    console.log(metadata);
}

And when I attempt to load the resulting compiled script in a simple index.html webpage:

<html>
    <head>
        <meta charset="utf-8" />
        <title>Icecast Metadata Testing</title>
    </head>
    <body>
        <button id="startStream">Start Stream</button>
        <h4 id="metdata"></h4>
    </body>
    <script src="main.js"></script>
</html>

I receive the following error in the console:

Uncaught ReferenceError: module is not defined
    at eval (IcecastMetadataQueue.js:101)
    at Object../node_modules/icecast-metadata-js/src/IcecastMetadataQueue.js (main.js:29)
    at __webpack_require__ (main.js:74)
    at eval (index.cjs:1)
    at Object../node_modules/icecast-metadata-js/index.cjs (main.js:18)
    at __webpack_require__ (main.js:74)
    at eval (index.js:1)
    at main.js:97
    at main.js:98
    at main.js:100

It seems that the compiled webpack main.js is referencing IcecastMetadataQueue.js for whatever reason, which has a module.exports directive inside that causes Chrome to throw a fit. Not sure why that's happening but getting things working is obviously not as easy as "webpack it and go."

I think I'll have to wait until #34 is complete. I'm unfamiliar with Node.JS and I don't feel like bashing my head against the wall until I figure things out.

from icecast-metadata-js.

eshaz avatar eshaz commented on August 16, 2024

Your code looks fine, actually this is a bug in the exports of icecast-metadata-js. Webpack is supposed to replace the CommonJS require and modules so the code works in a browser. I ran into the same issue while working on #34, and I'll be releasing a patch soon that fixes this.

from icecast-metadata-js.

W3AXL avatar W3AXL commented on August 16, 2024

Good to know it's not something on my end at least. Will be anxiously awaiting the updates!

from icecast-metadata-js.

eshaz avatar eshaz commented on August 16, 2024

@W3AXL I pushed a new release that should fix this issue for you. I was able to verify it worked locally using the default webpack configuration that gets generated when running npx webpack init

from icecast-metadata-js.

W3AXL avatar W3AXL commented on August 16, 2024

I now have IcecastReadableStream working with my stream! Metadata is being parsed perfectly.

However, I do have one more question I hope you can help me with. I'm not at all familiar with the inner workings of Media Source Extensions, and I'm having trouble getting the stream chunks to play. Hopefully this is the best place to ask.

If I simply add the stream chunks to my sourceBuffer object with appendBuffer(value.stream) as they come in, I get the somewhat well-documented error Failed to execute 'appendBuffer' on 'SourceBuffer': This SourceBuffer is still processing an 'appendBuffer' or 'remove' operation.

If I try to implement a basic buffering setup, waiting for the source to finish processing, such as :

function pushStream(value) {
    bufferQueue.push(value.stream);
    bufferAvail = true;
    if (!streaming) {
        console.log("starting source buffering loop");
        streaming = true;
        processBuffer();
        sourceBuffer.addEventListener('updateend', processBuffer);
    }
    console.log("Current buffer size: " + bufferQueue.length);
}

function processBuffer() {
    // push in new data if there's any available
    if (bufferAvail) {
        console.log("processing next chunk");
        sourceBuffer.appendBuffer(bufferQueue.shift());
        // if we used up all the buffer, set to false
        if (!bufferQueue.length) {
            bufferAvail = false;
        }
    }
}

the buffer continuously increases in size and I only get a small blip of audio at the beginning of the stream.

I guess that implies my stream is giving me data faster than the sourceBuffer can process the chunks? I would think it should be able to handle a low-bitrate mp3 stream without any issues.

Any suggestions?

from icecast-metadata-js.

eshaz avatar eshaz commented on August 16, 2024

@W3AXL That's great to hear that it's working with webpack now. The MSE api can be tricky, and the documentation / examples that I was able to find has been sporadic at best, at least that was the case when I originally wrote this code. The module I'm working on for #34 will do all of this for you, making this much simpler to just use off the shelf.

If you want to write this logic yourself, you can take a look here for a working example: https://github.com/eshaz/icecast-metadata-js/blob/master/src/demo/src/icecast/MetadataPlayer.js In the appendSourceBuffer method, there are a few calls to waitForSourceBuffer method that wraps the updateend event in a promise that resolves when the SourceBuffer is done updating. The SourceBuffer has to be done updating before any append or remove operations can happen.

async _waitForSourceBuffer() {
return new Promise((resolve) => {
this._sourceBuffer.addEventListener("updateend", resolve, { once: true });
});
}
async _appendSourceBuffer(chunk, mimeType) {
if (!this._mediaSource) await this._createMediaSource(mimeType);
this._sourceBuffer.appendBuffer(chunk);
await this._waitForSourceBuffer();
// buffer to remove flac skips
if (
this._playing &&
this._sourceBuffer.buffered.length &&
this._sourceBuffer.buffered.end(0) > 0.5
) {
this._playPromise = this._audioElement.play();
}
// keep last 2 seconds of audio in buffer
if (this._audioElement.currentTime > 2) {
this._sourceBuffer.remove(0, this._audioElement.currentTime - 2);
await this._waitForSourceBuffer();
}
}

from icecast-metadata-js.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.