Deep-Symmetry / beat-link-trigger

Trigger events and automate shows in response to events on Pioneer CDJs
Eclipse Public License 2.0
431 stars 37 forks source link

Write metadata to HTML for Open Broadcaster Studio streaming #46

Closed brunchboy closed 4 years ago

brunchboy commented 6 years ago

This was requested this in #43, but since it is not relevant there and I am closing that issue, I wanted to capture the request. This one is easy enough that it would be a good choice for someone who wants to start contributing to this project while I am busy on bigger tasks. (It doesn’t even need to be part of Beat Link Trigger, it is really just figuring how to write the appropriate trigger code, which could go on the Wiki.)

In a nutshell, the goal is to write a nicely formatted HTML file with metadata information about a track being played. I hope that @KayPure (the original requester) will comment here with additional details, such as:

KayPure commented 6 years ago

Thx @brunchboy best way is to output one file per player i think. saw a nicely overlay with some infos about artist - title - coverart - cued/played/stopped. and of course, there should be a delay between loading tracks in the decks and displaying tracks in the file. lets say, if a track played at least 30 or 60 seconds, the html should update. perhaps a way to change the format to whatever a user want?!

brunchboy commented 6 years ago

It would be up to you to format it; I would just provide a mechanism where your HTML could have values substituted from the track metadata when the right conditions (that you would define) take place. But since Evan has already built something like this, it makes more sense to just work with his solution.

evanpurkhiser commented 4 years ago

For posterity, here's the solution I builtin prolink-tools, but my interface looks like this:

http://prolink.tools/overlay

Though, mine is more geared towards a tracklist of songs played.

I also include some smart logic in the server itself to decide if a track should be listed or not described here https://github.com/EvanPurkhiser/prolink-tools/tree/master/server#mix-status

KayPure commented 4 years ago

Thats an awesome Tool and the overlay looks very smooth and modern. Just two things that won't work well for me.

  1. The new track updates on a specific playtime, right? So if a new track is played 1min, the overlay updates. Since i work with loops, that's a little bit confusing for viewers.
  2. The label metadata won't work. It displays nothing but my tags in the file are right I guess.

Is there a way to prevent the overlay displaying the new track after 1min. BT updates the playlist, if I hit the cue button on the track before. So, track 1 is displayed - track 2 is mixed in - after the transition I hit cue on track 1 and the playlist updates.

Greetings from Germany

brunchboy commented 4 years ago

@KayPure you should open an issue on the prolink-tools project to ask those questions as @EvanPurkhiser is more likely to see them there.

I’m trying to decide if I should write up some example trigger code for how to do this in Beat Link Trigger, or just close this issue and point people at Evan’s solution when they ask. 😄

brunchboy commented 4 years ago

Realistically, the only way I will ever do this is if I set up a Twitch stream of my own so I can experiment with OBS. Maybe this pandemic will be an excuse to do that.

KayPure commented 4 years ago

Yeah, didn't realized I was in the wrong git. I'm happy with beatlink for now. My trackupdate works just fine, except on few tracks, where no meta is displayed. That is maybe caused by a faulty tag.

brunchboy commented 4 years ago

Cool, you can check if anything shows up in the log file when loading one of those tracks. If so, it might be a fix required in the library.

obie commented 4 years ago

I know this is a little offtopic, but do any of you guys know if all this stuff works (or is supposed to work) with Rekordbox DJ in Performance mode (sans Pioneer equipment)?

brunchboy commented 4 years ago

No, unfortunately rekordbox in performance mode does not participate in a DJ link network, and does not share any information or respond to network requests that can be used by other software to do cool things like this. That’s why the only controller that can be integrated with is the XDJ-XZ, and only when it is being used in standalone/Link mode.

brunchboy commented 4 years ago

So I am actually starting to work on something along these lines. It’s not going to write to files, though, it is serving web pages on a port that you specify, and you will be able to point the OBS browser plugin at that. There is a nice templating language you can use to format the overlay with whatever information you want about the players and tracks, and you can replace the CSS to make it look however you want. I am planning to support rendering the waveforms as well as the artwork, but am just getting the basic plumbing working for now.

brunchboy commented 4 years ago

Forgot to tag this issue in the commit in which I started implementing this. a191753499acce372a4ee9826b9d78e154bb1796

brunchboy commented 4 years ago

Ok, folks, a preview release with the initial OBS overlay server has been published! You probably want to follow along on the Gitter channel for details, but it is ready for people to start poking at. I need to start documenting the parameters available to the overlay templates (there are a ton, way more than shows up in Player Status), but you can inspect them once the server is up using an Inspect button in the configuration window (which is accessed in the Network menu).

I still need to do a few more things beyond documentation, as well, like making the LED font I used in Player Status available for use in the template, and making waveform images available, but those things should be fun, I look forward to tackling them this week.

The templating language is inspired by Python Django, and implemented by Selmer, so you will want to start learning that.

My current test template is hideous and barely scratches the surface of what you can do, but here it is for reference:

<html>
  <head>
    <title>OBS Overlay</title>
    <link rel="stylesheet" type="text/css" href="styles.css">
  </head>
  <body>
    <p>
      Player 1: {{players.1.track.title}}—{{players.1.track.artist}}.
      <img src="artwork/1?icons=true" width="80" height="80">
    </p>
    <p>
      Player 2: {{players.2.track.title}}—{{players.2.track.artist}}.
      <img src="artwork/2?icons=true" width="80" height="80">
    </p>
  </body>
</html>

I hope people can start experimenting with this and contributing more useful and attractive templates to add to the user guide as examples.

Swiftb0y commented 4 years ago

Cool. I don't have any way to test this feature (yet) but it seems exciting. Will you provide a jumpstart/default template so people without webdesign experience can get up and running quickly?

brunchboy commented 4 years ago

There is a default template, but it currently is awful. So I certainly hope someone does come up with and share a much better one! I am not a web designer, and I haven’t yet installed or tried OBS Studio. But I can help people who use it, and who know a little CSS and HTML, to learn how to use the templating system and parameters I offer, and jointly we can come up with something better than I would be able to on my own. For now I am focusing on the parts that only I can do (for example, in addition to what I mentioned above, I need to add headers to the artwork responses to prevent the browser from caching stale information), but as those approach readiness, I will have more time to tinker with the default template itself.

brunchboy commented 4 years ago

Today I realized that instead of shutting the overlay server down when BLT is offline (not connected to a DJ Link network), it should instead continue to run, but provide sample data to the template. This will allow people to develop and fine-tune overlays even when they don’t have convenient access to players, and I already solved the “offline access to track data” problem in building the Show interface, so I can embed some sample data for the artwork and waveforms right inside BLT to make this work. I’ll finish off the rest first, but wanted to capture this idea here as a reminder.

brunchboy commented 4 years ago

All right, I think everything except for documentation (a big task!) and the above-noted idea of serving up sample data when Beat Link is not online with a DJ Link network, this server is finished. It can serve waveform preview and detail graphics showing the current state of the players, and properly sets cache-control headers for those and the album art. You can control the size of the waveforms, and the scale (zoom factor) of the waveform details. And I have restructured the template parameters to make it even easier to do things like iterating over the players with the help of Selmer, which is a very nice templating environment. This is going to be an incredibly powerful tool!

Now it is time to have people help me make some nice looking templates, and try them out in OBS itself. Here is the current state of the embedded sample template:

<html>
  <head>
    <title>OBS Overlay</title>
    <link rel="stylesheet" type="text/css" href="styles.css">
  </head>
  <body>
<!--
This is an example of how you can explicitly pull out information for specific players,
but generally you will want to use the loop approach below to get all players found on
the network.
    <p>
      Player 1: {{players.1.track.title}}—{{players.1.track.artist}}.
      <img src="artwork/1?icons=true" width="80" height="80">
    </p>
    <p>
      Player 2: {{players.2.track.title}}—{{players.2.track.artist}}.
      <img src="artwork/2?icons=true" width="80" height="80">
    </p>
-->

    {% for number, player in players|sort %}
    <p>
      <span class="player">Player {{number}}:</span>
      <img src="artwork/{{number}}?icons=true" width="80" height="80" align="middle">
      {{player.track.title}}—{{player.track.artist}}.

      <br><br>
      <img src="wave-detail/{{number}}?width=500">

      {% if player.time-played %}
      <br>
      <span class="timeLabel">Played</span>
      <span class="time">{{player.time-played.minutes|number-format:%02d}}</span><span class="timeSegmentLabel">M&thinsp;</span><span class="time">:{{player.time-played.seconds|number-format:%02d}}</span><span class="timeSegmentLabel">S&thinsp;</span><span class="time">:{{player.time-played.frames|number-format:%02d}}&thinsp;.&thinsp;</span><span class="timeFraction">{{player.time-played.frame-tenths}}</span><span class="timeSegmentLabel">F</span>
      {% endif %}

      {% if player.time-remaining %}
      <span class="remain">
        <span class="timeLabel">&nbsp;&nbsp;Remain</span>
        <span class="time">{{player.time-remaining.minutes|number-format:%02d}}</span><span class="timeSegmentLabel">M&thinsp;</span><span class="time">:{{player.time-remaining.seconds|number-format:%02d}}</span><span class="timeSegmentLabel">S&thinsp;</span><span class="time">:{{player.time-remaining.frames|number-format:%02d}}&thinsp;.&thinsp;</span><span class="timeFraction">{{player.time-remaining.frame-tenths}}</span><span class="timeSegmentLabel">F</span>
      </span>
      {% endif %}

      <br>
      <img src="wave-preview/{{number}}">
    </p>
    {% endfor %}
  </body>
</html>

And it uses this embedded style sheet to take advantage of the fonts served by BLT, which include the seven-segment LED font used for player timecode:

body {
    background-color: rgba(0, 0, 0, 0);
}

@font-face {
    font-family: dseg7;
    src: url(font/dseg7);
}

@font-face {
    font-family: orbitron;
    src: url(font/orbitron);
}
@font-face {
    font-family: orbitron;
    src: url(font/orbitron-bold);
    font-weight: bold;
}

@font-face {
    font-family: teko;
    src: url(font/teko);
}
@font-face {
    font-family: teko;
    src: url(font/teko-bold);
    font-weight: bold;
}

.player {
    font-family: orbitron;
}

.timeLabel {
    font-family: teko;
    font-size: 16pt;
}
.time {
    font-family: dseg7;
    font-size: 18pt;
}
.timeFraction {
    font-family: dseg7;
    font-size: 12pt;
}
.timeSegmentLabel {
    font-family: teko;
    font-weight: bold;
    font-size: 10pt;
}
.remain {
    color: red;
}
Kevinnns commented 4 years ago

Hey @brunchboy with Beat Link Trigger version 0.6.3-SNAPSHOT-19-0xf7cc built Thu May 28 06:49:50 UTC 2020 the webserver ran fine, with the latest build Beat Link Trigger version 0.6.3-SNAPSHOT-32-0x7cb6 built Mon Jun 01 06:03:11 UTC 2020 I can't seem to start the webserver.

You mentioned something about running BLT from the JAR file vs loose classes. So this might be the case not only on Windows, but also other compiled installers.

brunchboy commented 4 years ago

Thanks for calling this to my attention, @Kevinnns it turns out that the mechanism I was using to load sample data in case the OBS server is being used offline works great when the application is running from loose compiled classes, like it is when I am developing it, but fails miserably when it is running from a jar file, like it is when distributed. And I had to learn and deploy an insane amount of low-level Java plumbing to work around that. But there is a new preview building on GitHub right now that should work. The Windows build just finished, so you can test it at your convenience. The Mac build takes much longer because of the notarization step at Apple.

brunchboy commented 4 years ago

@Kevinnns found another problem, it seems setting up a custom template directory in Windows does not work. This looks like a problem in Selmer itself, https://github.com/yogthos/Selmer/issues/231

I am going to try forking that project and making the fixes the author proposed, changing BLT to use my fork temporarily, and testing it in a Windows VM (or with Kevin’s help, if he has time). If that works, I can submit a pull request to Selmer, and we will be able to move back to the main release once that is available.

brunchboy commented 4 years ago

OK, first step, I have reproduced Kevin’s issue in my VMWare Windows 10 environment. Now I am forking and trying to fix Selmer.

brunchboy commented 4 years ago

@Kevinnns (and everyone who might be affected), I have created a fixed version of Selmer, and just pushed a new preview build that uses it. Accessing custom templates on Windows is working in my VM, please let me know if it works for you as well now. Time to go for a walk before tonight’s protest-driven curfew sets in, make and eat dinner, and do a little more work on the user guide.

brunchboy commented 4 years ago

Selmer released my fix, so I moved back to that. And the first draft of the new User Guide section for this overlay server is done! https://blt-guide.deepsymmetry.org/beat-link-trigger/obsoverlay

Kevinnns commented 4 years ago

Verified it worked @brunchboy

brunchboy commented 4 years ago

My implementation of this seems to be working for people.