2020 Videogames

In 2020 I’m newly retired, so I’ve had free time. I think it’s fun to do reviews, so without further ado here’s every video game I played in 2020!

I recommend:

  • (4/5) Among Us – Very fun. It’s only fun with voice chat with friends, so I’ve only gotten to play once or twice. I’ve been watching it more than playing it. Also free to play for mobile gamers–I’m tired of the “everyone buys a copy” model of group gameplay.
  • (4/5) Brogue. Brogue is an ascii-art roguelike. It’s great, and it has a nice difficulty ramp. It’s a good “quick break” game. I play it in preference to other roguelikes partly because I haven’t done it to death yet, and partly because I don’t need a numpad?
  • (4/5) Cook Serve Delicious 3. One of the more fun games I played this year. You get really into it, but I had trouble relaxing and paying attention to the real world when I played too much, haha. I own but haven’t played the first two–I gather this is pretty much just a refinement.
  • (4/5) Green Hell. Price tag is a bit high for the number of hours I got out of it, but I haven’t finished the story. Great graphics, and the BEST map design I’ve seen in a 3D game in a long time. It feels like a real place, with reasonable geography instead of copy-pasted tiles. I love that as you walk along, you can just spot a cultivated area from the rest of the jungle–it feels more like it’s treating me like an adult than most survival games. Everything still gets highlighted if you can pick it up. I played the survival mode, which was okay but gets old quickly. I started the story mode–I think it would be fine, but it has some LONG unskippable scenes at the start, including a very hand-holdy tutorial, that I think they should have cut. I did start getting into the story and was having fun, but I stopped. I might finish the game some time.
  • (4/5) Hyperrogue. One of my recent favorites. The dev has made a fair number of highly experimental games, most of which are a total miss with me, but this one is fun. I do wish the early game wasn’t quite as repetitive. Failing another solution, I might actually want this not to be permadeath, or to have a save feature? I bought it on steam to support the dev and get achievements, but it’s also available a version or two behind free, which is how I tried it. Constantly getting updates and new worlds.
  • (4/5) Minecraft – Compact Claustrophobia modpack. Fun idea, nice variety. After one expansion felt a little samey, and it was hard to start with two people. I’d consider finishing this pack.
  • (4/5) Overcooked 2. Overcooked 2 is just more levels for Overcooked. The foods in the second game is more fun, and it has better controls and less bugs. If you’re considering playing Overcooked, I recommend just starting with the second game, despite very fun levels in the first. I especially appreciate that the second game didn’t just re-use foods from the first.
  • (4/5) Please Don’t Press Anything. A unique little game where you try to get all the endings. I had a lot of fun with this one, but it could have used some kind of built-in hints like Reventure. Also, it had a lot of red herrings. Got it for $2, which it was well worth.
  • (5/5) Reventure. Probably the best game new to me this year. It’s a short game where you try to get each of about 100 endings. The art and writing are cute and funny. The level design is INCREDIBLE. One thing I found interesting is the early prototype–if I had played it, I would NOT have imagined it would someday be any fun at all, let alone as amazing as it is. As a game designer I found that interesting! I did 100% complete this one–there’s a nice in-game hint system, but there were still 1-3 “huh” puzzles, especially in the post-game content, one of which I had to look up. It’s still getting updates so I’m hoping those will be swapped for something else.
  • (5/5) Rimworld. Dwarf fortress, but with good cute graphics, set in the Firefly universe. Only has 1-10 pawns instead of hundreds of dwarves. Basically Dwarf Fortress but with a good UI. I wish you could do a little more in Rimworld, but it’s a fantastic, relaxing game.
  • (5/5) Slay the Spire. Probably the game I played most this year. A deckbuilding adventure through a series of RPG fights. A bit luck-based, but relaxing and fun. I like that you can play fast or slow. Very, very well-designed UI–you can really learn how things work. My favorite part is that because it’s singleplayer, it’s really designed to let you build a game-breaking deck. That’s how it should be!
  • (4/5) Stationeers. I had a lot of fun with this one. It’s similar to Space Engineers but… fun. It has better UI by a mile too, even if it’s not perfect. I lost steam after playing with friends and then going back to being alone, as I often do for base-building games. Looks like you can genuinely make some complicated stuff using simple parts. Mining might not be ideal.
  • (5/5) Spy Party. One of my favorite games. Very fun, and an incredibly high skill ceiling. There’s finally starting to be enough people to play a game with straners sometimes. Bad support for “hot seat”–I want to play with beginners in person, and it got even harder with the introduction of an ELO equivalent and removing the manual switch to use “beginner” gameplay.
  • (4/5) Telling Lies. A storytelling game. The core mechanic is that you can use a search engine for any phrase, and it will show the top 5 survellance footage results for that. The game internally has transcripts of every video. I didn’t really finish the game, but I had a lot of fun with it. The game was well-made. I felt the video acting didn’t really add a huge amount, and they could have done a text version, but I understand it wouldn’t have had any popular appeal. The acting was decent. There’s some uncomfortable content, on purpose.
  • (4/5) Totally Accurate Battle Simulator (TABS). Delightful. Very silly, not what you’d expect from the name. What everyone should have been doing with physics engines since they were invented. Imagine that when a caveman attacks, the club moves on its own and the caveman just gets ragdolled along, glued to it. Also the caveman and club have googley eyes. Don’t try to win or it will stop being fun. Learn how to turn on slo-mo and move the camera.
  • (4/5) We Were Here Together. Lots of fun. I believe the second game out of three. Still some crashes and UI issues. MUCH better puzzles and the grpahics are gorgeous. They need to fix the crashes or improve the autosave, we ended up replaying a lot of both games from crashes. It’s possible I should be recommending the third game but I haven’t played it yet.

The Rest

  • (3/5) 5D Chess with Multiverse Time Travel. More fun that it sounds. If you play to mess around and win by accident, it’s pretty good. Definitely play with a second human player, though.
  • (1.5/5) 7 billion humans. Better than the original, still not fun. Soulless game about a soulless, beige corporation. Just play Zachtronics instead. If you’re on a phone and want to engage your brain, play Euclidea.
  • (3/5) A Dark Room. Idle game.
  • (1/5) Amazing Cultivation Simulator. A big disappointment. Bad english voice acting which can’t be turned off, and a long, unskippable tutorial. I didn’t get to actual gameplay. I like Rimworld and cultivation novels so I had high hopes.
  • (3/5) ADOM (Steam version) – Fun like the original, which I would give 5/5. Developed some major issues on Linux, but I appreciate that there’s a graphical version available, one of my friends will play it now.
  • (4/5) agar.io – Good, but used to be better. Too difficult to get into games now. Very fun and addictive gameplay.
  • (3/5) Amorous – Furry dating sim. All of the hot characters are background art you can’t interact with, and the characters you can actually talk to are a bunch of sulky nerds who for some reason came to a nightclub. I think it was free, though.
  • (0/5) Apis. Alpha game, AFAIK I was the first player. Pretty much no fun right now (to the point of not really being a game yet), but it could potentially become fun if the author puts in work.
  • (4/5) Autonauts. I played a ton of Autonauts this year, almost finished it, which is rare for me. My main complaint is that it’s fundamentally supposed to be a game about programming robots, but I can’t actually make them do more than about 3 things, even as a professional programmer. Add more programming! It can be optional, that’s fine. They’re adding some kind of tower defense waves instead, which is bullshit. Not recommended because it’s not for everyone.
  • (3/5) A-Z Inc. Points for having the guts to have a simple game. At first this looked like just the bones of Swarm Simulator, but the more you look at the UI and the ascension system, the worse it actually is. I would regularly reset because I found out an ascension “perk” actually made me worse off.
  • (5/5) Beat Saber. Great game, and my favorite way to stay in shape early this year. Oculus VR only, if you have VR you already have this game so no need to recommend. Not QUITE worth getting a VR set just to play it at current prices.
  • (1/5) Big Tall Small. Good idea, but no fun to play. Needed better controls and level design, maybe some art.
  • (0.5/5) Blush Blush. Boring.
  • (3/5) Business Shark. I had too much fun with this simple game. All you do is just eat a bunch of office workers.
  • (3/5) chess.com. Turns out I like chess while I’m high?
  • (3/5) Circle Empires Rivals. Decent, more fun than the singleplayer original. It shouldn’t really have been a separate game from Circle Empires, and I’m annoyed I couldn’t get it DRM-free like the original.
  • (3/5) Cross Virus. By Dan-box. Really interesting puzzle mechanics.
  • (4/5) Cultist Simulator. Really fun to learn how to play–I love games that drop you in with no explanation. Great art and writing, I wish I could have gotten their tarot deck. Probably the best gameplay “ambience” I’ve seen–getting a card that’s labeled “fleeting sense of radiance” that disappears in 5 seconds? Great. Also the core stats are very well thought out for “feel” and real-life accuracy–dread (depression) conquers fascination (mania), etc. It has a few gameplay gotchas, but they’re not too big–layout issues, inability to go back to skipped text, or to put your game in an unwinnable state early on). Unfortunately it’s a “roguelike”, and it’s much too slow-paced and doesn’t have enough replay value, so it becomes a horrible, un-fun grind when you want to actually win. I probably missed the 100% ending but I won’t be going back to get it. I have no idea who would want to play this repeatedly. I’m looking forward to the next game from the same studio though! I recommend playing a friend’s copy instead of buying.
  • (2/5) Darkest Dungeon. It was fine but I don’t really remember it.
  • (2/5) Dicey Dungeons. Okay deck-building roguelike gameplay (with an inventory instead of a deck). Really frustrating, unskippably slow difficulty curve at the start. I played it some more this year and liked it better because I had a savegame. I appreciate having several character classes, but they should unlock every difficulty from the start.
  • (2/5) Diner Bros. Basically just a worse Overcooked. I didn’t like the controls, and it felt too repetitive with only one diner.
  • (2/5) Don’t Eat My Mind You Stupid Monster. Okay art and idea, the gameplay wasn’t too fun for me.
  • (2/5) Don’t Starve – I’ve played Don’t Stave maybe 8 different times, and it’s never really gripped me, I always put it back down. It’s slow, a bit grindy, and there’s no bigger goal–all you can do is live.
  • (3/5) Don’t Starve Together – Confusingly, Don’t Starve Together can be played alone. It’s Don’t Starve, plus a couple of the expansions. This really could be much more clearly explained.
  • (1/5) Elemental Abyss – A deck-builder, but this time it’s grid-based tactics. Really not all that fun. Just play Into the Abyss instead or something.
  • (1/5) Else Heart.Break() – I was excited that this might be a version of “Hack N’ Slash” from doublefine that actually delivered and let you goof around with the world. I gave it up in the first ten minutes, because the writing and characters drove me crazy, without getting to hacking the world.
  • (2/5) Everything is Garbage. Pretty good for a game jam game. Not a bad use of 10 minutes. I do think it’s probably possible to make the game unwinnable, and the ending is just nothing.
  • (1/5) Evolve. Idle game, not all that fun. I take issue with the mechanic in Sharks, Kittens, and this where buying your 15th fence takes 10^15 wood for some reason.
  • (4/5) Exapunks. Zachtronics has really been killing it lately, with Exapunks and Opus Magnum. WONDERFUL art and characters during story portions, and much better writing. The gameplay is a little more varied than in TIS-100 or the little I played of ShenZen I/O. My main complaint about Zachtronics games continues to be, that I don’t want to be given a series of resource-limited puzzles (do X, but without using more than 10 programming instructions). Exapunks is the first game where it becomes harder to do something /at all/, rather than with a particular amount of resources, but it’s still not there for me. Like ShenZen, they really go for a variety of hardware, too. Can’t recommend this because it’s really only for programmers.
  • (1/5) Exception. Programming game written by some money machine mobile games company. Awful.
  • (4/5) Factorio. Factorio’s great, but for me it doesn’t have that much replay value, even with mods. I do like their recent updates, which included adding blueprints from the start of the game, improving belt sorting, and adding a research queue. We changed movement speed, made things visually always day, and adding a small number of personal construction robots from the start this run. I’m sure if you’d like factorio you’ve played it already.
  • (3/5) Fall Guys – I got this because it was decently fun to watch. Unfortunately, it’s slightly less fun to play. Overall, there’s WAY too much matchmaking waiting considering the number of players, and the skill ceiling is very low on most of the games, some of which are essentially luck (I’m looking at you, team games).
  • (3/5) Forager – Decent game. A little too much guesswork in picking upgrades–was probably a bit more fun on my second play because of that. Overall, nice graphics and a cute map, but the gameplay could use a bit of work.
  • (3/5) Getting Over It – Funny idea, executed well. Pretty sure my friends and I have only gotten through 10% of the game, and all hit about the same wall (the first tunnel)
  • (3/5) Guild of Dungeoneering – Pretty decent gameplay. I feel like it’s a bit too hard for me, but that’s fine. Overall I think it could use a little more cute/fun art, I never quite felt that motivated.
  • (1/5) Hardspace: Shipbreakers. Okay, I seriously didn’t get to play this one, but I had GAMEBREAKING issues with my controller, which is a microsoft X-box controller for PC–THE development controller.
  • (2/5) Helltaker. All right art, meh gameplay. But eh, it’s free!
  • (3/5) Hot Lava. Decent gameplay. Somehow felt like the place that made this had sucked the souls out of all the devs first–no one cared about the story or characters. It’s a game where the floor is made out of lava, with a saturday morning cartoon open, so that was a really an issue. Admirable lack of bugs, though. I’m a completionist so I played the first world a lot to get all the medals, and didn’t try the later ones.
  • (3/5) House Flipper – Weird, but I had fun. I wish the gameplay was a little more unified–it felt like a bunch of glued-together minigames.
  • (2/5) Hydroneer. Utterly uninspiring. I couldn’t care about making progress at all, looked like a terrible grind to no benefit.
  • (1/5) io. Tiny game, I got it on Steam, also available on phone. Basically a free web flash game, but for money. Not good enough to pay the $1 I paid. Just a bit of a time-killer.
  • (3/5) Islanders – All you do is place buildings and get points. Not particularly challenging, but relaxing. Overall I liked it.
  • (3/5) Jackbox – I played this online with a streamer. Jackbox has always felt a little bit soulless money grab to me, but it’s still all right. I like that I can play without having a copy–we need more games using this purchase model.
  • (3/5) Life is Feudal – Soul-crushingly depressing and grindy, which I knew going in. I thought it was… okay, but I really want an offline play mode (Yes, I know there’s an unsupported single-player game, but it’s buggier and costs money). UI was pretty buggy, and I think hunting might literally be impossible.
  • (2/5) Minecraft – Antimatter Chemistry. Not particularly fun.
  • (3/5) Minecraft – ComputerCraft. I played a pack with just ComputerCraft and really nothing else. Was a little slow, would have been more fun with more of an audience. I love the ComputerCraft mod, I just didn’t have a great experience playing my pack I made.
  • (3/5) Minecraft – Foolcraft 3. Fun, a bit buggy. Honestly I can’t remember it too well.
  • (1/5) Minecraft – Manufactio. Looked potentially fun, but huge bugs and performance issues, couldn’t play.
  • (4/5) Minecraft – Tekkit. Tekkit remains one of my favorite Minecraft modpacks.
  • (3/5) Minecraft – Valhelsia 2. I remember this being fun, but I can’t remember details as much as I’d like. I think it was mostly based around being the latest version of minecraft?
  • (4/5) Minecraft – Volcano Block. Interesting, designed around some weird mods I hadn’t used. I could have used more storage management or bulk dirt/blocks early in the game–felt quite cramped. Probably got a third of the way through the pack. I got novelty value out of it, but I wouldn’t have enjoyed it if I had ever used the plant mod before–it’s a very fixed, linear progression.
  • (5/5) Minit. This is a weird, small game. I actually had a lot of fun with it. Then I 100% completed it, which was less fun but I still had a good time overall.
  • (3/5) Monster Box. By Dan-box. One of two Dan-box games I played a lot of. Just visually appealing, the gameplay isn’t amazing. Also, Dan-box does some great programming–this is a game written in 1990 or so, and it can render hundreds of arrows in the air smoothly in a background tab.
  • (3/5) Monster Train. A relatively fun deckbuilding card game. It can’t run well on my computer, which is UNACCEPTABLE–this is a card game with 2D graphics. My MICROWAVE should run this shit in 2020. Ignoring that, the gameplay style (summon monsters, MTG style) just isn’t my cup of tea.
  • (2/5) Moonlighter. Felt like it was missing some inspiration, just didn’t have a sense of “fun”. The art was nice. The credits list is surprisingly long.
  • (2/5) Muse Dash. All right, a basic rhythm game. Not enough variety to the game play, and everything was based around perfect or near-perfect gameplay, which makes things less fun for me.
  • (3/5) NES games – various. Dr Mario, Ice Climbers. Basically, I got some Chinese handheld “gameboy” that has all the NES games preloaded on it. Overall it was a great purchase.
  • (2/5) Noita. “The Powder Game” by Dan-Box, as a procedurally generated platformer with guns. Lets you design your own battle spells. Despite the description, you really still can’t screw around as much as I’d like. I also had major performance issues
  • (3/5) Observation. I haven’t played this one as much as I’d like, I feel like it may get better. Storytelling, 3D game from the point of view of the AI computer on a space station. I think I might have read a book it’s based on, unfortunately.
  • (2/5) One Step From Eden. This is a deck-building combat tactics game. I thought it was turn-based, but it’s actually realtime. I think if it was turn-based I would have liked it. The characters were a bit uninspired.
  • (1/5) Orbt XL. Very dull. I paid $0.50 for it, it was worth that.
  • (4/5) Opus Magnum. Another great game from Zachtronics, along with Exapunks they’re really ramping up. This is the third execution of the same basic concept. I’d like to see Zachtronics treading new ground more as far as gameplay–that said, it is much improved compared to the first two iterations. The art, writing, and story were stellar on the other hand.
  • (3/5) Out of Space. Fun idea, you clean a spaceship. It’s never that challenging, and it has mechanics such that it gets easier the more you clean, rather than harder. Good but not enough replay value. Fun with friends the first few times. The controls are a little wonky.
  • (1/5) Outpost (tower defense game). I hate all tower defense.
  • (3/5) Overcooked. Overcooked is a ton of fun.
  • (4/5) Powder Game – Dan-box. I played this in reaction to not liking Noita. It’s fairly old at this point. Just a fun little toy.
  • (1/5) Prime Mover – Very cool art, the gameplay put me to sleep immediately. A “circuit builder” game but somehow missing any challenge or consistency.
  • (2/5) Quest for Glory I. Older, from 1989. Didn’t really play this much, I couldn’t get into the writing, and the pseudo-photography art was a little jarring.
  • (4/5) Raft. I played this in beta for free on itch.io, and had a lot of fun. Not enough changed that it was really worth a replay, but it has improved, and I got to play with a second player. Not a hard game, which I think was a good thing. The late game they’ve expanded, but it doesn’t really add much. The original was fun and so was this.
  • (3/5) Satisfactory. I honestly don’t know how I like this one–I didn’t get too far into it.
  • (4/5) Scrap Mechanic. I got this on a recommendation from a player who played in creative. I only tried the survival mode–that mode is not well designed, and their focuses for survival are totally wrong. I like the core game, you can actually build stuff. If I play again, I’ll try the creative mode, I think.
  • (3.5/5) Shapez.io. A weird, abstracted simplification of Factorio. If I hadn’t played factorio and half a dozen copies, I imagine this would have been fun, but it’s just more of the same. Too much waiting–blueprints are too far into the game, too.
  • (2.5/5) Simmiland. Okay, but short. Used cards for no reason. For a paid game, I wanted more gameplay out of it?
  • (0.5/5) Snakeybus. The most disappointing game I remember this year. Someone made “Snake” in 3D. There are a million game modes and worlds to play in. I didn’t find anything I tried much fun.
  • (1/5) Soda Dungeon. A “mobile” (read: not fun) style idle game. Patterned after money-grab games, although I don’t remember if paid progress was actually an option. I think so.
  • (4/5) Spelunky. The only procedurally generated platformer I’ve ever seen work. Genuinely very fun.
  • (4/5) Spelunky 2. Fun, more of an upgrade of new content than a new game. Better multiplayer. My computer can’t run later levels at full speed.
  • (1/5) Stick Ranger 2. Dan-box. Not much fun.
  • (3/5) Superliminal. Fun game. A bit short for the pricetag.
  • (3/5) Tabletop Simulator – Aether’s End: Legacy. Interesting, a “campaign” (series of challenge bosses and pre-written encounters) deckbuilding RPG. I like the whole “campaign RPG boardgame” idea. This would have worked better with paper, there were some rough edges in both the game instructions and the port to Tabletop Simulator.
  • (4/5) Tabletop Simulator – The Captain is Dead. Very fun. I’d love to play with more than 2 people. Tabletop simulator was so-so for this one.
  • (2/5) Tabletop Simulator – Tiny Epic Mechs. You give your mech a list of instructions, and it does them in order. Arena fight. Fun, but I think I could whip up something at least as good.
  • (3/5) The Council. One of the only 3D games I finished. It’s a story game, where you investigate what’s going on and make various choices. It’s set in revolutionary france, at the Secret World Council that determines the fate of the world. It had a weak ending, with less choice elements than the rest of the game so far, which was a weird decision. Also, it has an EXCRUTIATINGLY bad opening scene, which was also weird. The middle 95% of the game I enjoyed, although the ending went on a little long. The level of background knowledge expected of the player swung wildly–they seemed to expect me to know who revolutionary French generals were with no explanation, but not Daedalus and the Minotaur. The acting was generally enjoyable–there’s a lot of lying going on in the game and it’s conveyed well. The pricetag is too high to recommend.
  • (0/5) The Grandma’s Recipe (Unus Annus). This game is unplayably bad–it’s just a random pixel hunt. Maybe it would be fun if you had watched the video it’s based on.
  • (3/5) The Room. Pretty fun! I think this is really designed for a touchscreen, but I managed to play it on my PC. Played it stoned, which I think helps with popular puzzle games–it has nice visuals but it’s a little too easy.
  • (3/5) This Call May Be Recorded. Goofy experimental game.
  • (4/5) TIS-100. Zachtronics. A programming game. I finally got done with the first set of puzzles and into the second this year. I had fun, definitely not for everyone.
  • (3/5) Trine. I played this 2-player. I think the difficulty was much better 2-player, but it doesn’t manage 2 players getting separated well. Sadly we skipped the story, which seemed like simple nice low-fantasy. Could have used goofier puzzles, it took itself a little too seriously and the levels were a bit same-y.
  • (2/5) Unrailed. Co-op railroad building game. It was okay but there wasn’t base-building. Overall not my thing. I’d say I would prefer something like Overcooked if it’s going to be timed? Graphics reminded me of autonauts.
  • (2/5) Vampire Night Shift. Art game. Gameplay could have used a bit of polish. Short but interesting.
  • (4/5) Wayward. To date, the best survival crafting system I’ve seen. You can use any pointy object and stick-like object, together with glue or twine, to make an arrow. The UI is not great, and there’s a very counter-intuitive difficulty system. You need to do a little too much tutorial reading, and it could use more goals. Overall very fun. Under constant development, so how it plays a given week is a crapshoot. The steam version finally works for me (last time I played it was worse than the free online alpha, now it’s the same or better). I recomend playing the free online version unless you want to support the author.
  • (1/5) We Need to Go Deeper. Multiplayer exploration game in a sub, with sidescrolling battle. Somehow incredibly unfun, together with high pricetag. Aesthetics reminded me of Don’t Starve somehow.
  • (2/5) We Were Here. Okay 2-player puzzle game. Crashed frequently, and there were some “huh” puzzles and UI. Free.
  • (3/5) Yes, your grace. Gorgeous pixel art graphics. The story is supposed to be very player-dependent, but I started getting the feeling that it wasn’t. I didn’t quite finish the game but I think I was well past halfway. Hard to resume after a save, you forget things. I got the feeling I wouldn’t replay it, which is a shame because it’s fun to see how things go differently in a second play with something like this.

These are not all new to me, and very few came out in 2020. I removed any games I don’t remember and couldn’t google (a fair number, I play a lot of game jam games) as well as any with pornographic content.

Time log transcribed

I write down everything I do.

I transcribed my journals by hand. That is, I typed them up myself, instead of trying to use handwriting recognition or outsourcing to Mechanical Turk.

  • I started on 2019-11-02, and finished today, 2020-11-20. That’s roughly one year.
  • The 15 journals transcribed go from 2011 to 2020, 10 years. The 2011-2015 period is sparser.
  • Of the 15 journals, 13 of them them I transcribed from the physical version. Two I had thrown out, because my old scanner was feed-through, and I had to destroy the spines to scan the books.
  • That’s 1779 pages total (small ones, these are pocket journals). It’s also 32,000 lines, and 164K words. The text is 1.1MB, the scanned PNG files are 12GB (12000 MB).
  • In general, it takes me 1 hour to transcribe the last week of notes. Going farther back is harder, partly because my handwriting gets more readable as time progresses (due at least as much to my choice of pen, as my neatness), and partly because I have a harder time guessing at poor handwriting without memory to fill it in, and partly because I didn’t use standard formats back then.
  • I do have exact numbers I could check, but a lower bound based on this rate is that was overall 90 hours of work. It probably didn’t take more than twice that.

fabric1 AUR package

Fabric is a system administration tool used to run commands on remote machines over SSH. You program it using python. In 2018, Fabric 2 came out. In a lot of ways it’s better, but it’s incompatible, and removes some features I really need. I talked to the Fabric dev (bitprophet) and he seemed on board with keeping a Fabric 1 package around (and maybe renaming the current package to Fabric 2).

Here’s an arch package: https://aur.archlinux.org/packages/fabric1/

Currently Fabric 1 runs only on Python2. But there was a project to port it to Python 3 (confusingly named fabric3), which is currently attempting to merge into mainline fabric. Once that’s done, I’m hoping to see a ‘fabric1’ and ‘fabric2’ package in all the main distros.

mon(8)

I had previously hand-rolled a status monitor, status.za3k.com, which I am in the process of replacing (new version). I am replacing it with a linux monitoring daemon, mon, which I recommend. It is targeted at working system administrators. ‘mon’ adds many features over my own system, but still has a very bare-bones feeling.

The old service, ‘simple-status‘ worked as follows:

  • You visited the URL. Then, the status page would (live) kick of about 30 parallel jobs, to check the status of 30 services
  • The list of services is one-per-file in a the services.d directory.
  • For each service, it ran a short script, with no command line arguments.
  • All output is displayed in a simple html table, with the name of the service, the status (with color coding), and a short output line.
  • The script could return with a success (0) or non-success status code. If it returned success, that status line would display in green for success. If it failed, the line would be highlighted red for failure.
  • Scripts can be anything, but I wrote several utility functions to be called from scripts. For example, “ping?” checks whether a host is pingable.
  • Each script was wrapped in timeout. If the script took too long to run, it would be highlighted yellow.
  • The reason all scripts ran every time, is to prevent a failure mode where the information could ever be stale without me noticing.

Mon works as follows

  • The list of 30 services is defined in /etc/mon/con.cf.
  • For each service, it runs a single-line command (monitor) with arguments. The hostname(s) are added to the command line automatically.
  • All output can be displayed in a simple html table, with the name of the service, the status (with color coding), the time of last and next run, and a short output line. Or, I use ‘monshow‘, which is similar but in a text format.
  • Monitors can be anything, but several useful ones are provided in /usr/lib/mon/mon.d (on debian). For example the monitor “ping” checks whether a host is pingable.
  • The script could return with a success (0) or non-success status code. If it returned success, the status line would display in green for success (on the web interface), or red for failure.
  • All scripts run periodically. A script have many states, not just “success” or “failure”. For example “untested” (not yet run) or “dependency failing” (I assume, not yet seen).

As you can see, the two have a very similar approach to the component scripts, which is natural in the Linux world. Here is a comparison.

  • ‘simple-status’ does exactly one thing. ‘mon’ has many features, but does the minimum possible to provide each.
  • ‘simple-status’ is stateless. ‘mon’ has state.
  • ‘simple-status’ runs on demand. ‘mon’ is a daemon which runs monitors periodically.
  • Input is different. ‘simple-status’ is one script which takes a timeout. ‘mon’ listens for trap signals and talks to clients who want to know its state.
  • both can show an HTML status page that looks about the same, with some CGI parameters accepted.
  • ‘mon’ can also show a text status page.
  • both run monitors which return success based on status code, and provide extra information as standard output. ‘mon’ scripts are expected to be able to run on a list of hosts, rather than just one.
  • ‘mon’ has a config file. ‘simple-status’ has no options.
  • ‘simple-status’ is simple (27 lines). ‘mon’ has longer code (4922 lines)
  • ‘simple-status’ is written in bash, and does not expose this. ‘mon’ is written in perl, all the monitors are written in perl, and it allows inline perl in the config file
  • ‘simple-status’ limits the execution time of monitors. ‘mon’ does not.
  • ‘mon’ allows alerting, which call an arbitrary program to deliver the alert (email is common)
  • ‘mon’ supports traps, which are active alerts
  • ‘mon’ supports watchdog/heartbeat style alerts, where if a trap is not regularly received, it marks a service as failed.
  • ‘mon’ supports dependencies
  • ‘mon’ allows defining a service for several hosts at once

Overall I think that ‘mon’ is much more complex, but only to add features, and it doesn’t have a lot of features I wouldn’t use. It still is pretty simple with a simple interface. I recommend it as both good, and overall better than my system.

My only complaint is that it’s basically impossible to Google, which is why I’m writing a recommendation for it here.

Cron email, and sending email to only one address

So you want to know when your monitoring system fails, or your cron jobs don’t run? Add this to your crontab:

MAILTO=me@me.com

Now install a mail-sending agent. I like ‘nullmailer‘, which is much smaller than most mail-sending agents. It can’t receive or forward mail, only send it, which is what I like about it. No chance of a spammer using my server for something nasty.

The way I have it set up, I’ll have a server (avalanche) sending all email from one address (nullmailer@avalanche.za3k.com) to one email (admin@za3k.com), and that’s it. Here’s my setup on debian:

sudo apt-get install nullmailer
echo "admin@za3k.com" | sudo tee /etc/nullmailer/adminaddr # all mail is sent to here, except for certain patterns
echo "nullmailer@`hostname`.za3k.com" | sudo tee /etc/nullmailer/allmailfrom # all mail is sent from here
echo "`hostname`.za3k.com" | sudo tee /etc/nullmailer/defaultdomain # superceded by 'allmailfrom' and not used
echo "`hostname`.za3k.com" | sudo tee /etc/nullmailer/helohost # required to connect to my server. otherwise default to 'me'
echo "smtp.za3k.com smtp --port=587 --starttls" | sudo tee /etc/nullmailer/remotes && sudo chmod 600 /etc/nullmailer/remotes

Now just run echo "Subject: sendmail test" | /usr/lib/sendmail -v admin@za3k.com to test and you’re done!

Postmortem: bs-store

Between 2020-03-14 and 2020-12-03 I ran an experimental computer storage setup. I movied or copied 90% of my files into a content-addressable storage system. I’m doing a writeup of why I did it, how I did it, and why I stopped. My hope is that it will be useful to anyone considering using a similar system.

The assumption behind this setup, is that 99% of my files never change, so it’s fine to store only one, static copy of them. (Think movies, photos… they’re most of your computer space, and you’re never going to modify them). There are files you change, I just didn’t put them into this system. If you run a database, this ain’t for you.

Because I have quite a lot of files and 42 drives (7 in my computer, ~35 in a huge media server chassis), there is a problem of how to organize files across drives. To explain why it’s a problem, let’s look at the two default approaches:

  • One Block Device / RAID 0. Use some form of system that unifies block devices, such as RAID0 or a ZFS’s striped vdevs. Writing files is very easy, you see a single 3000GB drive.
    • Many forms of RAID0 use striping. Striping splits each file across all available drives. 42 drives could spin up to read one file (wasteful).
    • You need all the drives mounted to read anything–I have ~40 drives, and I’d like a solution that works if I move and can’t keep my giant media server running. Also, it’s just more reassuring that nothing can fail if you can read each drive individually.
  • JBOD / Just a Bunch of Disks. Label each drive with a category (ex. ‘movies’), and mount them individually.
    • It’s hard to aim for 100% (or even >80%) drive use. Say you have 4x 1000GB drives, and you have 800GB movies, 800GB home video footage, 100GB photographs, and 300GB datasets. How do you arrange that? One drive per dataset is pretty wasteful, as everything fits on 3. But, with three drives, you’ll need to split at least one dataset across drives. Say you put together 800GB home video and 100GB photographs. If you get 200GB more photographs, do you split a 300 GB collection across drives, or move the entire thing to another drive? It’s a lot of manual management and shifting things around for little reason.

Neither approach adds any redundancy, and 42 drives is a bit too many to deal with for most things. Step 1 is to split the 42 drives into 7 ZFS vdevs, each with 2-drive redundancy. That way, if a drive fails or there is a small data corruption (likely), everything will keep working. So now we only have to think about accessing 7 drives (but keep in mind, many physical drives will spin up for each disk access).

The ideal solution:

  • Will not involve a lot of manual management
  • Will fill up each drive in turn to 100%, rather than all drives at an equal %.
  • Will deduplicate identical content (this is a “nice to have”)
  • Will only involve accessing one drive to access one file
  • Will allow me to get and remove drives, ideally across heterogenous systems.

I decided a content-addressable system was ideal for me. That is, you’d look up each file by its hash. I don’t like having an extra step to access files, so files would be accessed by symlink–no frontend program. Also, it was important to me that I be able to transparently swap out the set of drives backing this. I wanted to make the content-addressable system basically a set of 7 content-addressable systems, and somehow wrap those all into one big content-addressable system with the same interface. Here’s what I settled on:

  • (My drives are mounted as /zpool/bs0, /zpool/bs1, … /zpool/bs6)
  • Files will be stored in each pool in turn by hash. So my movie ‘cat.mpg’ with sha hash ‘8323f58d8b92e6fdf190c56594ed767df90f1b6d’ gets stored in /zpool/bs0/83/23/f58d8b9 [shortened for readability]
  • Initially, we just copy files into the content-addressable system, we don’t delete the original. I’m cautious, and I wanted to make everything worked before getting rid of the originals.
  • To access a file, I used read-only unionfs-fuse for this. This checks each of /zpool/bs{0..6}/<hash> in turn. So in the final version, /data/movies/cat.mpg would be a symlink to ‘/bs-union/83/23/f58d8b9’
  • We store some extra metadata on the original file (if not replaced by a symlink) and the storied copy–what collection it’s part of, when it was added, how big it is, what it’s hash is, etc. I chose to use xattrs.

The plan here is that it would be really easy to swap out one backing blockstore of 30GB, for two of 20GB–just copy the files to the new drives and add it to the unionfs.

Here’s what went well:

  • No problems during development–only copying files meant it was easy and safe to debug prototypes.
  • Everything was trivial to access (except see note about mounting disks below)
  • It was easy to add things to the system
  • Holding off on deleting the original content until I was 100% out of room on my room disks, meant it was easy to migrate off of, rather risk-free
  • Running the entire thing on top of zfs ZRAID2 was the right decision, I had no worries about failing drives or data corruption, despite a lot of hardware issues developing at one point.
  • My assumption that files would never change was correct. I made the unionfs filesystem read-only as a guard against error, but it was never a problem.
  • Migrating off the system went smoothly

Here are the implementation problems I found

  • I wrote the entire thing as bash scripts operating directly on files, which was OK for access and putting stuff in the store, but just awful for trying to get an overview of data or migrating things. I definitely should have used a database. I maybe should have used a programming language.
  • Because there was no database, there wasn’t really any kind of regular check for orphans (content in the blobstore with no symlinks to it), and other similar checks.
  • unionfs-fuse suuucks. Every union filesystem I’ve tried sucks. Its read bandwidth is much lower than the component devices (unclear, probably), it doesn’t cache where to look things up, and it has zero xattrs support (can’t read xattrs from the underlying filesystem).
  • gotcha: zfs xattrs waste a lot of space by default, you need to reconfigure the default.

But the biggest problem was disk access patterns:

  • I thought I could cool 42 drives spinning, or at least a good portion of them. This was WRONG by far, and I am not sure how possible it is in a home setup. To give you an idea how bad this was, I had to write a monitor to shut off my computer if the drives went above 60C, and I was developing fevers in my bedroom (where the server is) from overheating. Not healthy.
  • unionfs has to check each backing drive. So we see 42 drives spin up. I have ideas on fixing this, but it doesn’t deal with the other problems
  • To fix this, you could use double-indirection.
    • Rather than pointing a symlink at a unionfs: /data/cat.mpg -> /bs-union/83/23/f58d8b9 (which accesses /zpool/bs0/83/23/f58d8b9)
    • Point a symlink at another symlink that points directly to the data: /data/cat.mpg -> /bs-indirect/83/23/f58d8b9 -> /zpool/bs0/83/23/f58d8b9
  • The idea is that backing stores are kinda “whatever, just shove it somewhere”. But, actually it would be good to have a collection in one place–not only to make it easy to copy, but to spin up only one drive when you go through everything in a collection. It might even be a good idea to have a separate drive for more frequently-accessed content. This wasn’t a huge deal for me since migrating existing content meant it coincidentally ended up pretty localized.
  • Because I couldn’t spin up all 42 drives, I had to keep a lot of the array unmounted, and mount the drives I needed into the unionfs manually.

So although I could have tried to fix things with double-indirection, I decided there were some other disadvantages to symlinks: estimating sizes, making offsite backups foolproof. I decided to migrate off the system entirely. The migration went well, although it required running all the drives at once, so some hardware errors popped up. I’m currently on a semi-JBOD system (still on top of the same 7 ZRAID2 devices).

Hopefully this is useful to someone planning a similar system someday. If you learned something useful, or there are existing systems I should have used, feel free to leave a comment.

Printing on the Brother HL-2270DW printer using a Raspberry Pi

Although the below directions work on Raspberry Pi, they should also work on any other system. The brother-provided driver does not run on arm processors[1] like the raspberry pi, so we will instead use the open-source brlaser[2].

Edit: This setup should also work on the following Brother monochrome printers, just substitute the name where needed:

  • brlaser 4, just install from package manager: DCP-1510, DCP-1600 series, DCP-7030, DCP-7040, DCP-7055, DCP-7055W, DCP-7060D, DCP-7065DN, DCP-7080, DCP-L2500D series, HL-1110 series, HL-1200 series, HL-L2300D series, HL-L2320D series, HL-L2340D series, HL-L2360D series, HL-L2375DW series, HL-L2390DW, MFC-1910W, MFC-7240, MFC-7360N, MFC-7365DN, MFC-7420, MFC-7460DN, MFC-7840W, MFC-L2710DW series
  • brlaser 6, follow full steps below: DCP-L2520D series, DCP-L2520DW series, DCP-L2540DW series (unclear, may only need 4), HL-2030 series, HL-2140 series, HL-2220 series, HL-2270DW series, HL-5030 series

Also, all these steps are command-line based, and you can do the whole setup headless (no monitor or keyboard) using SSH.

  1. Get the latest raspbian image up and running on your pi, with working networking. At the time of writing the latest version is 10 (buster)–once 11+ is released this will be much easier. I have written a convenience tool[3] for this step, but you can also find any number of standard guides. Log into your raspberry pi to run the following steps
  2. (Option 1, not recommended) Upgrade to Debian 11 bullseye (current testing release). This is because we need brlaser 6, not brlaser 4 from debian 10 buster (current stable release). Then, install the print system and driver[2]:
    sudo apt-get update && sudo apt-get install lpr cups ghostscript printer-driver-brlaser
  3. (Option 2, recommended) Install ‘brlaser’ from source.
    1. Install print system and build tools
      sudo apt-get update && sudo apt-get install lpr cups ghostscript git cmake libcups2-dev libcupsimage2-dev
    2. Download the source
      wget https://github.com/pdewacht/brlaser/archive/v6.tar.gz && tar xf v6.tar.gz
    3. Build the source and install
      cd brlaser-6 && cmake . && make && sudo make install
  4. Plug in the printer, verify that it shows up using sudo lsusb or sudo dmesg. (author’s shameful note: if you’re not looking, I find it surprisingly easy to plug USB B into the ethernet jack)
  5. Install the printer.
    1. Run sudo lpinfo -v | grep usb to get the device name of your printer. It will be something like usb://Brother/HL-2270DW%20series?serial=D4N207646
      If you’re following this in the hopes that it will work on another printer, run sudo lpinfo -m | grep HL-2270DW to get the PPD file for your printer.
    2. Install and enable the printer
      sudo lpadmin -p HL-2270DW -E -v usb://Brother/HL-2270DW%20series?serial=D4N207646 -m drv:///brlaser.drv/br2270dw.ppd
      Note, -p HL-2270DW is just the name I’m using for the printer, feel free to name the printer whatever you like.
    3. Enable the printer (did not work for me)
      sudo lpadmin -p HL-2270DW -E
    4. (Optional) Set the printer as the default destination
      sudo lpoptions -d HL-2270DW
    5. (Optional) Set any default options you want for the printer
      sudo lpoptions -p HL-2270DW -o media=letter
  6. Test the printer (I’m in the USA so we use ‘letter’ size paper, you can substitute whichever paper you have such as ‘a4’).
    1. echo "Hello World" | PRINTER=HL-2270DW lp -o media=letter (Make sure anything prints)
    2. cat <test document> | PRINTER=HL-2270DW lp -o media=letter (Print an actual test page to test alignment, etc)
    3. cat <test document> | PRINTER=HL-2270DW lp -o media=letter -o sides=two-sided-short-edge (Make sure duplex works if you plan to use that)
  7. (Optional) Set up an scp print server, so any file you copy to a /printme directory gets printed. For the 2270DW, I also have a /printme.duplex directory.

Links
[1] brother driver does not work on arm (also verified myself)
[2] brlaser, the open-source Brother printer driver
[3] rpi-setup, my convenience command-line script for headless raspberry pi setup
[4] stack overflow answer on how to install one package from testing in debian

Streaming Linux->Twitch using ffmpeg and ALSA

I stopped using OBS a while ago for a couple reasons–the main one was that it didn’t support my video capture card, but I also had issues with it crashing or lagging behind with no clear indication of what it was doing. I ended up switching to ffmpeg for live streaming, because it’s very easy to tell when ffmpeg is lagging behind. OBS uses ffmpeg internally for video. I don’t especially recommend this setup, but I thought I’d document it in case someone can’t use a nice GUI setup like OBS or similar.

I’m prefer less layers, so I’m still on ALSA. My setup is:

  • I have one computer, running linux. It runs what I’m streaming (typically minecraft), and captures everything, encodes everything, and sends it to twitch
  • Video is captured using libxcb (captures X11 desktop)
  • Audio is captured using ALSA. My mic is captured directly, while the rest of my desktop audio is sent to a loopback device which acts as a second mic.
  • Everything is encoded together into one video stream. The video is a Flash video container with x264 video and AAC audio, because that’s what twitch wants. Hopefully we’ll all switch to AV1 soon.
  • That stream is sent to twitch by ffmpeg
  • There is no way to pause the stream, do scenes, adjust audio, see audio levels, etc while the stream is going. I just have to adjust program volumes independently.

Here’s my .asoundrc:

# sudo modprobe snd-aloop is required to set up hw:Loopback
pcm.!default {
  type plug
  slave.pcm {
    type dmix
    ipc_key 99
    slave {
      pcm "hw:Loopback,0"
      rate 48000
      channels 2
      period_size 1024
    }
  }
}

My ffmpeg build line:

./configure --enable-libfdk-aac --enable-nonfree --enable-libxcb --enable-indev=alsa --enable-outdev=alsa --prefix=/usr/local --extra-version='za3k' --toolchain=hardened --libdir=/usr/lib/x86_64-linux-gnu --incdir=/usr/include/x86_64-linux-gnu --arch=amd64 --enable-gpl --disable-stripping --enable-avresample --disable-filter=resample --enable-avisynth --enable-libaom --enable-libass --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libmp3lame --enable-libopus --enable-libpulse --enable-libvorbis --enable-libvpx --enable-libx265 --enable-opengl --enable-libdrm --enable-libx264 --enable-shared --enable-librtmp && make -j 4 && sudo make install

And most imporantly, my ffmpeg command:

ffmpeg 
  -video_size 1280x720 -framerate 30 -f x11grab -s 1280x720 -r 30 -i :0.0 
  -f alsa -ac 1 -ar 48000 -i hw:1,0 
  -f alsa -ac 2 -ar 48000 -i hw:Loopback,1
  -filter_complex '[1:a][1:a]amerge=inputs=2[stereo1] ; [2:a][stereo1]amerge=inputs=2[a]' -ac 2 
  -map '[a]' -map 0:v 
  -f flv -ac 2 -ar 48000 
  -vcodec libx264 -g 60 -keyint_min 30 -b:v 3000k -minrate 3000k -maxrate 3000k -pix_fmt yuv420p -s 1280x720 -preset ultrafast -tune film 
  -c:a libfdk_aac -b:a 160k -strict normal -bufsize 3000k 
  rtmp://live-sjc.twitch.tv/app/${TWITCH_KEY}

Let’s break that monster down a bit. ffmpeg structures its command line into input streams, transformations, and output streams.

ffmpeg input streams

-video_size 1280x720 -framerate 30 -f x11grab -s 1280x720 -r 30 -i :0.0:
Grab 720p video (-video_size 1280x720) at 30fps (-framerate 30) using x11grab/libxcb (-f x11grab), and we also want to output that video at the same resolution and framerate (-s 1280x720 -r 30). We grab :0.0 (-i :0.0)–that’s X language for first X server (you only have one, probably), first display/monitor. And, since we don’t say otherwise, we grab the whole thing, so the monitor better be 720p.

-f alsa -ac 1 -ar 48000 -i hw:1,0:
Using alsa (-f alsa), capture mono (-ac 1, 1 audio channel) at the standard PC sample rate (-ar 48000, audio rate=48000 Hz). The ALSA device is hw:1,0 (-i hw:1,0), my microphone, which happens to be mono.

-f alsa -ac 2 -ar 48000 -i hw:Loopback,1:
Using alsa (-f alsa), capture stereo (-ac 2, 2 audio channels) at the standard PC sample rate (-ar 48000, audio rate=48000 Hz). The ALSA device is hw:Loopback,1. In the ALSA config file .asoundrc given above, you can see we send all computer audio to hw:Loopback,0. Something sent to play on hw:Loopback,0 is made available to record as hw:Loopback,1, that’s just the convention for how snd-aloop devices work.

ffmpeg transforms

-filter_complex '[1:a][1:a]amerge=inputs=2[stereo1] ; [2:a][stereo1]amerge=inputs=2[a]' -ac 2:
All right, this one was a bit of a doozy to figure out. In ffmpeg’s special filter notation, 1:a means “stream #1, audio” (where stream #0 is the first one).

First we take the mic input [1:a][1:a] and convert it from a mono channel to stereo, by just duplicating the sound to both ears (amerge=inputs=2[stereo1]). Then, we combine the stereo mic and the stereo computer audio ([2:a][stereo1]) into a single stereo stream using the default mixer (amerge=inputs=2[a]).

-map '[a]' -map 0:v :
By default, ffmpeg just keeps all the streams around, so we now have one mono, and two stereo streams, and it won’t default to picking the last one. So we manually tell it to keep that last audio stream we made (-map '[a]'), and the video stream from the first input (-map 0:v, the only video stream).

ffmpeg output streams

-f flv -ac 2 -ar 48000:
We want the output format to be Flash video (-f flv) with stereo audio (-ac 2) at 48000Hz (-ar 48000). Why do we want that? Because we’re streaming to Twitch and that’s what Twitch says they want–that’s basically why everything in the output format.

-vcodec libx264 -g 60 -keyint_min 30 -b:v3000k -minrate 3000k -maxrate 3000k -pix_fmt yuv420p -s 1280x720 -preset ultrafast -tune film:
Ah, the magic. Now we do x264 encoding (-vcodec libx264), a modern wonder. A lot of the options here are just what Twitch requests. They want keyframes every 2 seconds (-g 60 -keyint_min 30, where 60=30*2=FPS*2, 30=FPS). They want a constant bitrate (-b:v3000k -minrate 3000k -maxrate 3000k) between 1K-6K/s at the time of writing–I picked 3K because it’s appropriate for 720p video, but you could go with 6K for 1080p. Here are Twitch’s recommendations. The pixel format is standard (-pix_gmt yub720p) and we still don’t want to change the resolution (-s 1280x720). Finally the options you might want to change. You want to set the preset as high as it will go with your computer keeping up–mine sucks (-preset ultrafast, where the options go ultrafast,superfast,veryfast,faster,fast,medium, with a 2-10X jump in CPU power needed for each step). And I’m broadcasting minecraft, which in terms of encoders is close to film (-tune film)–lots of panning, relatively complicated stuff on screen. If you want to re-encode cartoons you want something else.

-c:a libfdk_aac -b:a 160k:
We use AAC (-c:a libfdk_aac). Note that libfdk is many times faster than the default implementation, but it’s not available by default in debian’s ffmpeg for (dumb) license reasons. We use 160k bitrate (-b:a 160k ) audio since I’ve found that’s good, and 96K-160K is Twitch’s allowable range. `-strict normal`

-strict normal: Just an ffmpeg option. Not interesting.
-bufsize 3000k: One second of buffer with CBR video

rtmp://live-sjc.twitch.tv/app/${TWITCH_KEY}:
The twitch streaming URL. Replace ${TWITCH_KEY} with your actual key, of course.

Sources:

  • jrayhawk on IRC (alsa)
  • ffmpeg wiki and docs (pretty good)
  • ALSA docs (not that good)
  • Twitch documentation, which is pretty good once you can find it
  • mark hills on how to set up snd-aloop