All projects Pitcher · Write-up

A new tempo, the same keyNeues Tempo, gleiche Tonart

Pitcher plays a YouTube track at the tempo you type, the key held or resampled. It reads the tempo, the beat grid and the key in the browser, and a WebAssembly stretcher plays it, so testing a bootleg takes a paste and a number.Pitcher spielt einen YouTube-Track im Tempo, das man eintippt, die Tonart gehalten oder resampelt. Tempo, Beat-Raster und Tonart liest es im Browser, und ein Stretcher in WebAssembly spielt ihn ab, so braucht der Test eines Bootlegs ein Einfügen und eine Zahl.

pitcher.ewolution.cloud Source

Type
Web appWeb-App
Stack
Svelte 5 · WebAssembly · Node
Year
2026
Code
Public on GitHubÖffentlich auf GitHub

A test before the DAW

A bootleg starts with a question: does this track still work at 128? Pitcher answers it with a paste and a number. Paste a YouTube link anywhere on the page, or drop an audio file, and the track opens at the tempo you used last, so a session at 140 stays at 140. Type a new tempo into the big number, or drag the ruler below it and throw it: it settles on a genre stop when it ends near one, House 124, Tech house 128, Techno 132, Drum & bass 174. The arrow keys nudge by a tenth of a BPM, or a whole one with Shift.

What a tempo change does to the key is a switch. Keep key, the default, stretches the track and holds its key. Resample lets the pitch follow the tempo, the way a record plays faster and higher and the way FL Studio stretches by default: 116 to 128 BPM is 1.70 semitones up. The key moves on its own too, a semitone at a time, or to any key on the Camelot wheel, where the slices that mix with it are tinted. The rest is what a test needs: a kick on every beat at the new tempo, a held button for the original, loops of 4, 8 or 16 bars, a jump to YouTube’s most replayed part, and Copy, which writes the numbers for the DAW and a link that opens the same test.

Reading the track

Before it plays, the page reads the track in a worker. Two filters split it into three bands, below 150 Hz, up to 2.5 kHz and above, and each band’s peak every 10 ms draws the waveform in the colours DJ software uses: blue lows, amber mids, white highs. The same bands give the tempo. How sharply each one gets louder becomes an onset envelope; its autocorrelation finds the tempo’s neighbourhood, with a gentle preference for tempos near 125 to decide between a tempo and its half or double. Then the whole envelope is folded at every candidate period, a hundredth of a BPM apart: at the right one every beat lands in the same few of 64 bins, at a slightly wrong one they smear across the track. The fold also gives the beat’s phase, and the bar starts where the lows rise most.

The key comes from a chromagram: the track at about 11 kHz, a Fourier transform every 4,096 samples, and the energy between 65 Hz and 2.1 kHz added up per pitch class. The 24 major and minor keys are each a profile of how much each pitch class belongs (Krumhansl and Kessler’s), and the closest one wins. Get Lucky reads as 116 BPM in F♯ minor, 11A; a relative major or minor is the usual miss, so the detected tempo and key can be corrected in place, and half and double time are a button each.

0.01 BPMThe steps the tempo search folds at.
1.70 st116 to 128 BPM, resampled.
24Keys on the Camelot wheel, a fifth apart from slice to slice.

Tempo and pitch apart

Playback runs through Signalsmith Stretch, an MIT-licensed time-stretcher compiled to WebAssembly and run in an audio worklet, which changes tempo and pitch independently. The playhead lives in the worklet; each change merges into its schedule, so a new tempo or loop mid-play keeps the place. Resample is the same node with its pitch set to the tempo’s ratio, twelve times its base-2 logarithm in semitones. The kick is synthesised, a falling sine, and scheduled a little ahead at the moment the stretched playhead reaches each beat of the source’s grid, also across a loop’s end. Past ±25 % the stretch smears the sound, and the page says so: fine for judging an idea, not for the finished bootleg.

Through Fermata’s relay

YouTube sends no CORS headers and signs its stream addresses for the address that asked, so a page can’t fetch the audio on its own. Pitcher uses Fermata’s way: a small relay on the server that forwards requests to YouTube’s hosts only and passes the bytes back unread, and in the page youtubei.js, with Fermata’s chain of clients and its check of each stream’s last bytes. Pitcher takes the best audio-only stream, AAC before Opus because every browser decodes it, and fetches it in 1 MB ranges over four connections into memory. Nothing is written to disk on either side. The security headers allow exactly what that needs: YouTube’s cipher has to be evaluated, and the stretcher’s worklet arrives as a blob running WebAssembly.

Part of the family

The address keeps the test, /?v=…&bpm=128&st=1, and a YouTube link with the host swapped for Pitcher’s opens it too. Recent tracks and their settings stay on the device. The tokens and components come from Folio, the family’s shared library, the page works in English and German, light and dark, installs to the home screen, and the visit counter, Census, works without cookies.

Ein Test vor der DAW

Ein Bootleg beginnt mit einer Frage: Funktioniert dieser Track noch bei 128? Pitcher beantwortet sie mit einem Einfügen und einer Zahl. Einen YouTube-Link irgendwo auf der Seite einfügen oder eine Audiodatei ablegen, und der Track öffnet im zuletzt benutzten Tempo, so bleibt eine Session bei 140 bei 140. Ein neues Tempo in die große Zahl tippen oder das Lineal darunter ziehen und werfen: Es landet auf einem Genre, wenn es in dessen Nähe ausläuft, House 124, Tech House 128, Techno 132, Drum & Bass 174. Die Pfeiltasten schieben um ein Zehntel BPM, mit Umschalt um ein ganzes.

Was eine Tempoänderung mit der Tonart macht, ist ein Schalter. „Tonart halten“, voreingestellt, streckt den Track und hält seine Tonart. „Resample“ lässt die Tonhöhe dem Tempo folgen, so wie eine Platte schneller und höher läuft und wie FL Studio standardmäßig streckt: Von 116 auf 128 BPM sind es 1,70 Halbtöne nach oben. Die Tonart lässt sich auch für sich bewegen, einen Halbton nach dem anderen oder zu jeder Tonart auf dem Camelot-Rad, wo die Stücke getönt sind, die dazu passen. Der Rest ist, was ein Test braucht: eine Kick auf jedem Schlag im neuen Tempo, ein gehaltener Knopf für das Original, Loops über 4, 8 oder 16 Takte, ein Sprung zur meistgehörten Stelle auf YouTube und „Kopieren“, das die Zahlen für die DAW schreibt und einen Link, der denselben Test öffnet.

Den Track lesen

Bevor er spielt, liest die Seite den Track in einem Worker. Zwei Filter teilen ihn in drei Bänder, unter 150 Hz, bis 2,5 kHz und darüber, und die Spitze jedes Bands alle 10 ms zeichnet die Wellenform in den Farben, die DJ-Software benutzt: blaue Tiefen, bernsteinfarbene Mitten, weiße Höhen. Dieselben Bänder ergeben das Tempo. Wie scharf jedes lauter wird, wird zu einer Einsatzkurve; ihre Autokorrelation findet die Gegend des Tempos, mit einer leichten Vorliebe für Tempi um 125, die zwischen einem Tempo und seinem halben oder doppelten entscheidet. Dann wird die ganze Kurve bei jeder Kandidatenperiode gefaltet, eine Hundertstel BPM auseinander: Bei der richtigen landet jeder Schlag in denselben wenigen von 64 Fächern, bei einer leicht falschen verschmieren sie über den Track. Die Faltung liefert auch die Phase des Schlags, und der Takt beginnt, wo die Tiefen am stärksten steigen.

Die Tonart kommt aus einem Chromagramm: der Track bei etwa 11 kHz, eine Fourier-Transformation alle 4.096 Samples und die Energie zwischen 65 Hz und 2,1 kHz, je Tonklasse aufaddiert. Die 24 Dur- und Molltonarten sind jede ein Profil, wie sehr jede Tonklasse dazugehört (das von Krumhansl und Kessler), und das nächste gewinnt. Get Lucky liest sich als 116 BPM in Fis-Moll, 11A; eine parallele Dur- oder Molltonart ist der übliche Fehlgriff, deshalb lassen sich erkanntes Tempo und Tonart an Ort und Stelle korrigieren, und halbes und doppeltes Tempo sind je ein Knopf.

0,01 BPMDie Schritte, in denen die Temposuche faltet.
1,70 HT116 auf 128 BPM, resampelt.
24Tonarten auf dem Camelot-Rad, eine Quinte von Stück zu Stück.

Tempo und Tonhöhe getrennt

Abgespielt wird über Signalsmith Stretch, einen MIT-lizenzierten Time-Stretcher, kompiliert zu WebAssembly und in einem Audio-Worklet ausgeführt, der Tempo und Tonhöhe unabhängig ändert. Der Abspielkopf lebt im Worklet; jede Änderung fügt sich in seinen Ablaufplan ein, so behält ein neues Tempo oder ein Loop mitten im Spielen die Stelle. Resample ist derselbe Knoten mit der Tonhöhe auf das Verhältnis der Tempi gesetzt, zwölfmal sein Logarithmus zur Basis 2 in Halbtönen. Die Kick ist synthetisiert, ein fallender Sinus, und wird etwas im Voraus auf den Moment gelegt, in dem der gestreckte Abspielkopf jeden Schlag des Quellrasters erreicht, auch über das Ende eines Loops hinweg. Über ±25 % verschmiert die Streckung den Klang, und die Seite sagt das: gut genug, um eine Idee zu beurteilen, nicht für das fertige Bootleg.

Über Fermatas Relay

YouTube schickt keine CORS-Header und signiert seine Stream-Adressen für die Adresse, die gefragt hat, also kann eine Seite die Audiospur nicht selbst holen. Pitcher macht es wie Fermata: ein kleines Relay auf dem Server, das Anfragen nur an YouTubes Hosts weiterreicht und die Bytes ungelesen zurückgibt, und in der Seite youtubei.js, mit Fermatas Kette von Clients und seiner Prüfung der letzten Bytes jedes Streams. Pitcher nimmt den besten reinen Audio-Stream, AAC vor Opus, weil jeder Browser es dekodiert, und holt ihn in Stücken zu 1 MB über vier Verbindungen in den Speicher. Auf keiner Seite wird etwas auf die Platte geschrieben. Die Sicherheits-Header erlauben genau, was das braucht: YouTubes Chiffre muss ausgewertet werden, und das Worklet des Stretchers kommt als Blob, der WebAssembly ausführt.

Teil der Familie

Die Adresse hält den Test fest, /?v=…&bpm=128&st=1, und ein YouTube-Link, dessen Host gegen den von Pitcher getauscht ist, öffnet ihn auch. Zuletzt gehörte Tracks und ihre Einstellungen bleiben auf dem Gerät. Tokens und Komponenten kommen aus Folio, der gemeinsamen Bibliothek der Familie, die Seite gibt es auf Englisch und Deutsch, hell und dunkel, sie lässt sich auf den Home-Bildschirm legen, und der Besuchszähler Census kommt ohne Cookies aus.