DeeFuzzer icon indicating copy to clipboard operation
DeeFuzzer copied to clipboard

Follow metadata in time from CUE or JSON files

Open daslicht opened this issue 11 years ago • 17 comments

Hello is it feasible to create a Radio Station only with DeeFuzzer which have the following features: Stream seamless prerecorded DJ Mixes which are essentially one BIG audio file and provide the listener with Song Information. (for each song in the mix)

I have tried different approaches like Icecast / Shoutcast. Just playing a Playlist with files or with crossfades is not good enough. (always audible glitches especially if you have a continious 4/4 trance beat) The only really seamless solution I have found so far, was using Icecast and foobar2000 (the only cue-sheet player i have found and it is for windows!) + edcast dsp (no longer maintained?) playing a cue sheet wich contains the necessary Song Information.

To display the metadata on a webpage I have parsed the audio stream with nodejs and pushed the songinfo via socketio to a htm5 based client.

While this approach is "working" I am looking for something more solid.

Can you use cuesheets (or something similar) with DeeFuzzer Regards Marc

daslicht avatar Mar 23 '13 10:03 daslicht

Hi,

DeeFuzzer can stream playlist in alphanumeric or random order. It can NOT crossfade anything between cues as is it designed to be VERY light and stable (near zero CPU load), streaming audio or video files as they are in scalable environments.

For the file/stream metadata reading, my approach is to parse all files from the playlist before the first streaming process on the serverside. Deefuzzer generates two RSS XML files including the full metadata and optional file link enclosures (podcasting) : the whole playlist and the current playing track. As the "current" one is refreshed between each track playback, it can be used as a pseudo-realtime stream (at the average track time scale..). Also, the whole playlist is in RAM and is then accessible from various internal or external (OSC protocol) functions.

The XML files (could be a JSON stream) can then be parsed on the client side to display things. As an example, I did the whole thing for DeeFuzz radio using rssajax.js: http://deefuzz.parisson.com/

But, even this is a solid and old school architecture, the parsing is done every 5s on the web pages (with a static file access each time) and is in not so much scalable in my opinion... Your metadata streaming process seems interesting because using socketio which could decrease the workload and provide various cool realtime web functions or effects coming from the server. I'd be interested to see some examples of your experimentations and methods. Maybe we could extend the DeeFuzzer on such things.

Guillaume

yomguy avatar Mar 23 '13 16:03 yomguy

Thank you for the reply , there is no need to crossfade when using a cue sheet. A cue sheet is just a text containing something like this:

PERFORMER "BSO, William Steinberg"
TITLE "Also Sprach Zarathustra - Die Planeten"
FILE "Also sprach Zarathustra - Die Planeten.wav" WAVE
  TRACK 01 AUDIO
    TITLE "Also sprach Zarathustra - Einleitung"
    PERFORMER "BSO, William Steinberg"
    INDEX 01 00:00:00
  TRACK 02 AUDIO
    TITLE "Also sprach Zarathustra - Von den Hinterweltlern"
    PERFORMER "BSO, William Steinberg"
    INDEX 01 02:00:28
    ...

syntax: http://digitalx.org/cue-sheet/syntax/

So it's just playing ONE big audio file, but with metadata related to the current playback time If we could use something like this we wont need to parse the files anymore.

Currently I use this here to parse the icecast stream: https://github.com/TooTallNate/node-icecast

It has a handler for the metadata change, which looks like this:

function sendSongInfo(){
        if(_socket!==null){
            console.log('SONG ',_parsed);
            _socket.emit('updateSongInfo', _parsed); //very easy with socketIO
        }
    }
...
 res.on('metadata', function (metadata) {
          _parsed = icecast.parse(metadata);
          sendSongInfo();
          console.error('PARSED:',_parsed);
      });

I bet there is something similar to SocketIO available for python either ? Here is my test : http://78.47.126.11:3001 The stream parsing however isn't 100% stable.

can you get the current playback position of the file in the playlist in DeeFuzz ? If so we could compare it with the start times in the cue-shet and send teh metadata to the clients on-change.

~Marc

daslicht avatar Mar 23 '13 16:03 daslicht

Essentially we dont need that cuesheet at all we could also use a json or xml containing the metadata and the start time

daslicht avatar Mar 23 '13 16:03 daslicht

Hi Marc,

Thanks a lot for these examples. I'll look forward to what can be achieve in DeeFuzzer in terms of websocket cool functions.

I'm afraid DeeFuzzer cannot get the track playback time nor seeking in a big audio file... It is really designed to push / stream series of mp3 or ogg files, even big, without regarding the time scale.

However, the idea is good and I will look further to implement something that can push some metadata to the icecast server reading a cue sheet and relatively to an internal clock timer. So I'll try this module soon: http://audiotools.sourceforge.net/programming/audiotools_cue.html

I think a good usage would be then to scan any .cue file around the audio with the same filename and parse it if exists.

yomguy avatar Mar 25 '13 16:03 yomguy

Thak you very much ! On 25.03.2013, at 17:49, Guillaume Pellerin [email protected] wrote:

Hi Marc,

Thanks a lot for these examples. I'll look forward to what can be achieve in DeeFuzzer in terms of websocket cool functions.

I'm afraid DeeFuzzer cannot get the track playback time nor seeking in a big audio file... It is really designed to push / stream series of mp3 or ogg files, even big, without regarding the time scale.

However, the idea is good and I will look further to implement something that can push some metadata to the icecast server reading a cue sheet and relatively to an internal clock timer. So I'll try this module soon: http://audiotools.sourceforge.net/programming/audiotools_cue.html

I think a good usage would be then to scan any .cue file around the audio with the same filename and parse it if exists.

— Reply to this email directly or view it on GitHub.

daslicht avatar Mar 25 '13 16:03 daslicht

Any news on this?

daslicht avatar Apr 14 '14 20:04 daslicht

Hi @daslicht! I'm afraid not, but I'm starting the development again.. So maybe soon ;)

yomguy avatar May 23 '14 14:05 yomguy

Great news yomguy :+1:

ChoiZ avatar May 30 '14 08:05 ChoiZ

:+1:

daslicht avatar May 30 '14 13:05 daslicht

I've been using a workaround that involves parsing the file through Audacity, breaking it up into distinct MP3 files (with correct metadata), and loading that up into a folder which Deefuzzer then pushes to the streaming server. This may be an option short-term, but it is more work.

A cue file for metadata would be kind of neat for setting the metadata instead of breaking up the file and would definitely make my life less complicated. Ideally it would be specified as a "source" so we can use the most data from the file. We would have to add detection of CUE vs M3U. We could then use a timer on each station object that is checked against the cue listing every time a packet of data is sent, and updating metadata when needed? That's probably the cleanest thing I can think of.

achbed avatar Jan 24 '15 06:01 achbed

@achbed is the transition between 2 cutted files seamless or do you hear a glitch, click etc ?

daslicht avatar Jan 24 '15 11:01 daslicht

It's been seamless for me. I'm running it on a VPS with an SSD-based drive, so your mileage may vary depending on what hardware you throw at it.

achbed avatar Jan 24 '15 17:01 achbed

Hm interesting

daslicht avatar Jan 24 '15 17:01 daslicht

Although we can of course split a mix into separated files, as the transition is seamless on many tested systems here, I agree the internal timer - probably based on datetime.now() - solution is the best. The only pb is to setup, from another thread, a good time period to checkout the system time and trig the metadata update if it is superior to the time of the track relatively. Maybe we also have also to impose something like placing the cue file in the same directory than the media and naming it in a good way so that the link can be deduced. If you don't mind, I rename this isssue from "DeeFuzzer Radio Station" to "Follow metadata in time from CUE or JSON files".

yomguy avatar Jan 24 '15 23:01 yomguy

Started tackling this as part of a rewrite of the playlist structure. I've created a new branch (dsw-playlist-object) on my fork to track this. Basically I'm re-implementing the internal playlist of a station to allow for better use of class structures and improve future expandability.

There are two new classes: playlist and track. Playlist contains the list of tracks and all code to maintain the track list (including parsing various playlist file types like M3U and CUE, randomization, next track code, currently playing metadata, etc).

Track contains the media file reference and cached metadata, and can have multiple metadata entries for each track. The metadata is referenced by a timestamp (# of whole seconds) for when the metadata is first valid. This metadata is set either at initialization time (ie, it's from the playlist file), or is read from the media file if there's no metadata set otherwise.

achbed avatar Jan 25 '15 04:01 achbed

Great news !

daslicht avatar Jan 25 '15 11:01 daslicht

Any news on teh cuesheet or similar to support one source file ?

daslicht avatar Mar 18 '16 08:03 daslicht