Skip to content

Instantly share code, notes, and snippets.

View hlfbt's full-sized avatar
🤔

Alexander Schulz hlfbt

🤔
View GitHub Profile
@hlfbt
hlfbt / twitch_clips_issue_2024.md
Last active September 7, 2024 10:16
Twitch introduced an update to clips in the summer of 2024 that, while technically clever, sadly results in inconsistent decoding.

That timing issue of clips on twitch is interesting.

Here is an example clip with the described issue: https://www.twitch.tv/patty/clip/ThoughtfulMoldyGarlicWutFace-BeJzyXTm1kfwGKPK
You will notice that the video starts at different times (compare the on-screen timer in the bottom left of the stream) on Firefox and Chrome/Chromium.

Preface: Video codecs usually don't just save "full" frames for every frame, instead they save changes only and only every now and then have a "keyframe" or "I" frame that is a full frame, upon which consecutive frames base their changes on (these are called "B" and "P" frames).
There is nothing that dictates that an MPEG container must start with a keyframe from what I could tell.
But realistically, what is a decoder supposed to draw when it receives an intermediate (B/P) frame first? Green background with the changes on top? Looks shit. Most decoders will simply skip until the next keyframe.
Now, MPEG, among tons of other metadata, also stores timestamps for every s

@hlfbt
hlfbt / i3-focus-nth.py
Last active July 13, 2024 15:29 — forked from syl20bnr/i3_focus_win.py
Python script for i3 which allows to focus the nth window of the current container hierarchy.It requires i3ipc: https://github.com/altdesktop/i3ipc-python
#!/usr/bin/env python
#
# author: syl20bnr (2013), hlfbt (2024)
# goal: Focus the nth window in the current workspace (limited to 10 firsts)
# dependencies: i3ipc
#
# Example of usage in i3 config:
#
# bindsym $mod+0 exec i3-focus-nth.py -n 0
# bindsym $mod+1 exec i3-focus-nth.py -n 1
@hlfbt
hlfbt / fc2int.js
Created November 25, 2019 04:07
Convert Nintendo friend codes to plain old integers, for whatever reason you might want to do that anyway
function fc2int(fc) {
const codes = '0123456789ABCDEFGHJKLMNPQRSTUVWXY';
fc = fc.toUpperCase().match(new RegExp(`[${codes}]`, 'g'));
return -1 + fc
.map((a, i) => (codes.indexOf(a) + 1) * Math.pow(codes.length - 1, i))
.reduce((a, b) => a + b);
}
@hlfbt
hlfbt / getopts.sh
Created May 3, 2019 13:46
Simple somewhat advanced getopts only dependent on bash and expr
#!/bin/bash
# Simple more advanced arguments parsing than builtin tools like getopts or a simple while/case looping over the arguments
#
# Features include handling of:
# - multiple grouped shorthands (f.i. -abc becoming -a -b -c),
# - equal sign value assignment (f.i. --arg=value becoming --arg value, and also -a=value becoming -a value)
# - dashless value assignment (f.i. arg=value becoming arg value)
#
# The only dependencies are bash (for arrays) and expr (included in coreutils) (for regexp matching and extraction) which are likely available everywhere (even in a busybox or on a mac!)
#
@hlfbt
hlfbt / debug_modifiers.java
Created March 21, 2019 23:22
Get a human readable list of all modifiers on a given Method or Field
/*
This isn't supposed to be pretty or ever be used in production code (don't even think about it), but has proven useful for quick debugging when working with reflections.
*/
// Example Method with some more interesting modifiers
Method meth = Arrays.stream(data.getClass().getDeclaredMethods()).filter(m -> "getChronology".equals(m.getName())).toArray()[0];
// Should return "isSynthetic, isPublic, isVolatile"
String modifiers = Arrays.stream(Modifier.class.getDeclaredMethods())
.map(m -> {
@hlfbt
hlfbt / twitch_color_switcher.js
Last active April 10, 2022 01:28
Twitch Color Switcher for you bad bad kids out there. Enable with `enableColorSwitcher(<switching_interval_in_seconds>)` and disable again by reloading or calling `disableColorSwitcher()`.
let oauthToken = document.cookie.match(/auth-token=([0-9a-z]+);/)[1];
const updateChatColor = function (chatColor) {
fetch('https://gql.twitch.tv/gql', {
method: 'POST',
body: JSON.stringify({
query:
`mutation Chat_UpdateChatColor(\$input: UpdateChatColorInput!) {
updateChatColor(input: \$input) {
user {
@hlfbt
hlfbt / amazon_total_tally.js
Created October 14, 2018 00:48
Does a tally of amount spent, orders and items ordered on amazon. To be executed on any amazon order history page.
function fetchPage(link, callback) {
var xhr = new XMLHttpRequest();
xhr.open('get', link);
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200)
callback.call(xhr, xhr);
};
xhr.send();
@hlfbt
hlfbt / guid.js
Created September 16, 2018 17:31
Generate random GUIDs usable as element IDs (first character is always a letter)
(function () {
var S4 = function (n, d) {
return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1) + (n > 1 ? (d || '') + S4(n - 1, d) : '');
};
return (String.fromCharCode(97 + Math.floor(Math.random() * 26)) + S4().substring(1) + S4(5, '-') + S4(2));
})();
@hlfbt
hlfbt / objectify.js
Last active February 5, 2018 13:57
Generic object class construction
/**
* GenericObject / objectify.js
*
* Creating new objects with neat setters and getters over again is annoying, so let's automate it.
*
* @author Alexander Schulz ([email protected])
*/
var Objectify = (function () {
"use strict";
@hlfbt
hlfbt / object_search.js
Last active February 22, 2017 15:28
Searches through an object for an identifier
/*
* Recurses through an object to search for an identifier.
* Identifier is a RegExp.
* Returns either the first match or false.
*/
function search (obj, term) {
for (var k in obj) {
if (obj.hasOwnProperty(k)) {
if (k == term) return k;