/tinyletter

The Programs of the Week After a Vacation

This Week’s Program: June 5 - June 9

I’m back from a week-long vacation. Vacations are wonderful things. It was wonderful to step away from the computer. This week I’ve slowly adjusted to getting back into the coding groove, and spent the time thinking critically about how I wanted to shape and evolve this API. It seems like forever since I did my first live broadcast with Overscan. There’s still so much I’d like to refine about this project though, and this week I took a few spikes that ended up not really going anywhere, but now I have a greater sense of what direction I want this project to head in.

bfe15032c8236e152d6a5ed8908e1b1ba77e4ac1

Here’s Monday’s vacation commit, quickly written on my iPad from my FreeBSD server. I just add a link to my Twitch profile to my website.

Make sure to follow me on Twitch @ Wunschkraft. I’m going to be focusing most of my broadcasting energy to Twitch. I thought I might spend some time preparing streaming to YouTube or Facebook Live, but I think I’d rather focus on building out the API around scenes and mixing video and audio sources on one streaming platform before attacking the others.

I haven’t done another broadcast since May 25, and I’d like to build out a little bit more functionality before my next one.

801d141419f3d8cfe57be86b230346d300f0452d

Tuesday’s commit changes the signature of gobject-set! just slightly. This is the function used to set properties of GObjects, and GStreamer uses properties really frequently. Before this change I had to explicitly indicate what ctype the property I was setting was. The contract is here:

[gobject-set!
    (-> gobject? string? any/c ctype? void?)]

This contract says this function takes a GObject instance, a String property name, any value, a C-Type, and returns void. Internally, Racket’s FFI attempts to coerce the value to the given C-Type.

After this commit, the contract has changed to this:

[gobject-set!
    (->* (gobject? string? any/c)
         ((or/c ctype? (listof symbol?)))
         void?)]

This change to the function signature shows that gobject-set! now accepts a GObject instance, a String property name, and a value, and optionally takes either a C-Type or a List of Symbols.

If this optional argument is not given, it is inferred based on the value that’s been passed in. If a list of symbols is given, that list is automatically transformed into a C Enum type.

This makes for a much cleaner API up in the GStreamer layers, where we can now do things like:

(gobject-set! videosrc "device-index" 0)

Instead of

(gobject-set! videosrc "device-index" 0 _int)

This means that modules that rely on GObject Introspection might not need a deep knowledge of Racket’s FFI and the C types being used.

7ec07b088f64d1f43199c10afa29111cdd5cecde

This commit introduces another function around setting GObject properties: gobject-with-properties accepts a GObject instance and a Hash map of keys and values, and returns the GObject instance after setting properties.

Frequently in the overscan code you see something like:

(let ([el (send avfvideosrc create "screen")])
    (gobject-set! el "capture-screen" #t _bool)
    (gobject-set! el "device-index" ref _int)
    el)

In this code I’m instantiating a GObject (in this case, a GStreamer Element), setting some properties on it, and then returning the instance.

With the gobject-with-properties function, this code is equivalent to:

(gobject-with-properties (send avfvideosrc create "screen")
                         (hash 'capture-screen #t
                               'device-index ref))

Which is nicer, I think. I was also thinking of making this a macro of something along the lines of:

(gobject-with-properties ([capture-screen #t]
                          [device-index ref])
    (send avfvideosrc create "screen"))

What do you think of that syntax? Do you have a preference? I’m on the fence, but I think the Hash style might be better.

90dddc52a8fbf469783f2ef7e1bfd8df2c3425d4

In this commit I swap out the x264 encoder back to Apple’s VideoToolbox hardware encoder. This encoder, besides being provided by Apple, takes advantage of the GPU, so my hope is that this can free up some of the CPU that video encoding normally consumes. We’ll see how this impacts the stream.

This week I also did a spike that I ended up scrapping on changing the broadcast API.

Right now the broadcast function accepts a list of scenes and a place to stream to (and some optional params for previewing, monitoring, and recording). I tried to change this a little bit to accept a list of sources along with a list of scenes. The idea being that each scene would become a function of available sources. The problem was I couldn’t quite figure out an API that made this easy. Each source would have to have an associated tee Element to output to possibly multiple scenes. It wasn’t clear how to filter down the source list to get just the sources you want in a way that seemed natural. I stashed this in Git and decided it wasn’t worth exploring now.

I might try to instead have the scene functionality be entirely focused on video, and have a separate audio mixer parameter to the broadcast function. This way, scenes always share the same audio. Still brewing this idea.

Here’s a short list of things that I’d like to try to work on in the coming weeks:

  • Documentation. Racket has a robust documentation tool called Scribble that appears to me to be pretty critical for the Racket ecosystem. I’d like to start writing some documentation, especially around some of the GObject Introspection work, now that it’s stabilized.
  • Text Overlays. Before Overscan was Overscan it was called Chyron. This whole project started as a way to do compositing for live streaming video. Now that I have the basics, I’d like to add the ability to dynamically overlay text on the scene.
  • Separation of Concerns. I think now is a good time to begin splitting out parts of the codebase into different files. For example, separating out the interface for GObjects that mimic Racket’s Class collection.

I expect that I’ll do a blend of these things over the course of the next week, and might jump on Twitch to demo and try some things out.

– Mark