Fork me on GitHub

Here is a simple video encoding library for Clojure: I wrote this as an example of how simple interfacing with C systems can be and to show how nice using the deps.edn pathway is for a clojure library. It sits directly on top of the libavcodec series of shared libraries used by ffmpeg - it loads them dynamically and then you pass frames directly to the library. I have included a simple example of using Skija to render to a native buffer that is then passed directly into the encode-frame! method. Use this if you have a need to render videos of your crazy Clojure pixel art 🙂.

🎉 50
📹 6
👏 3

This is really neat! Would it be possible to make a simple video player using avclj?


Yes it would be possible. The decode pathways in my opinion are much harder than the encode pathways but all the necessary pieces are there. I could provide a function that gives you a sequence of close-able buffer objects or something that had each frame's information such as the image, the microsecond time and duration. The waters are fairly deep with FFmpeg; the encoder took a lot of head scratching before it produced videos that worked on cellphones.


FFmpeg is such a useful library, it's something I've been meaning to dive into myself. I'm familiar with jna and it would probably be good for me to also learn from how you've been using jna based off your excellent work with libpython-clj. I'll check it out and see how it goes.


wow, I did not know about this trick, Very cool. I've been using python-clang to try to get struct info.


🤯 , this stuff is awesome, Is the ffi stuff graalvm compatible?


Not at this time. I am working on it right now. It is JNA and JDK-16 compatible.


Well, either way, there's some really great c interop code here and I look forward to simplifying some of my c interop code in the future. Thanks! :thumbsup:


You are so welcome! I will post of course when I get a graal native pathway working. The target is some clojure code along with some python stuff all wrapped up into a graal native shared library that is then loaded via cython.

metal 3

Eventually, I'd like to be able to spit out apps a shared library that can be loaded and ran on mobile using a prebuilt iOS/android app

metal 4
Adam Helins15:03:15

Dear friends, a new much improved version of BinF, a Clojure/script library for handling any kind of binary formats /protocols in a simple yet powerful way. I've used it with great success for things like MIDI processing and a WebAssembly decompiler. I find it really capable, flexible, and feature-rich. It provides probably more than you need. Hope it will sprout new super use cases:

👍 9
catjam 4

Nice. I have a Node-hosted sysex librarian to finish. This could well be useful.


This looks great! I also nominate your READMEs description of your support for 64-bit integers for the "README Hall of Fame":

It is not the most beautiful experience one will encounter in the course of a lifetime but it works and does the job pretty efficiently.

Adam Helins22:03:42

Then I shall accept the honor!


The award will, of course, be in binary.

😁 7
🔟 4
Alex Miller (Clojure team)19:03:25

After a slight delay, is now available! • Clojure keyword argument functions now also accept a map, see

bananadance 52
clj 85
💯 49
👍 16
🎉 25
sheepy 4
🤯 3

user=> (let [[& {:keys [a b] :as opts}] [{:a 1 :b 2}]] [a b opts])
[1 2 {:a 1, :b 2}]
user=> (let [[& {:keys [a b] :as opts}] [:a 1 :b 2]] [a b opts])
[1 2 {:a 1, :b 2}]


Compared to 1.10.3:

Clojure 1.10.3
user=> (let [[& {:keys [a b] :as opts}] [{:a 1 :b 2}]] [a b opts])
Execution error (IllegalArgumentException) at user/eval140 (REPL:1).
No value supplied for key: {:a 1, :b 2}
user=> (let [[& {:keys [a b] :as opts}] [:a 1 :b 2]] [a b opts])
[1 2 {:b 2, :a 1}]


So, no, it changes destructuring “everywhere”.


@U050CT4HR You’re trying to destructuring a sequence as a map — the change in 1.11 is the other way round, effectively, destructuring a map as a sequence of named arguments.


I will update us to 1.11 Alpha 1 at work and see if it breaks anything!

Alex Miller (Clojure team)19:03:31

I should also mention that the destructuring docs have also been updated (they actually never had been updated to include keyword argument support and there were no published semantics about that anywhere). Also, the doc has been extended to cover this new 1.11 capability


This seems like a clever little change though to be honest I don't like the kw-args approach, I'm always happy enough to just use an optional map parameter on my functions. A lot of confusion to save two characters. It's feels like a rare example of Clojure doing something "to be cool looking" (the kw args in the first place, not this new change).


Also, I think the example in the release notes would be slightly more useful if it showed a mix of kw args and a map.


Is there a performance difference between using the new & and no & at all? (i.e. a vanilla, fixed map arg)

Alex Miller (Clojure team)06:03:09

well you're comparing doing work and not doing work, and usually doing work has some cost, so yes

Alex Miller (Clojure team)06:03:30

although kwarg destructuring in general is significantly faster than it was due to the other changes in the patch

Alex Miller (Clojure team)06:03:04

given something like (defn foo [& {:as m}] (count m)) , running (time (dotimes [_ 500000] (foo :a 1 :b 2))) a few times shows best case around 70 ms on 1.10.3 and 14 ms on 1.11.0-alpha1. vs (defn foo-m [m] (count m)) and (time (dotimes [_ 500000] (foo-m {:a 1 :b 2}))) of around 7.5 ms.

Alex Miller (Clojure team)06:03:27

there's a lot of "it depends" in those numbers, but might give you some idea


Thanks, that's useful! I asked partly because I was under the impression that for the following programmer intent:

(defn foo [& {:keys [a b c]}]) could emit internally two arities. In Clojure pseudocode:
(defn foo
  ([k v & kvs]))
The point being, if you invoke the arity 1 (by using {} caller-side instead of kwargs), you'd get the best possible performance. Which would seem a sweet spot: one can opt to consume defns in a more performant way, while keeping full flexibility.

Alex Miller (Clojure team)08:03:50

yes, that was one of many options we considered

👍 4
🙂 4