You are browsing as a guest. Sign up (or log in) to start making projects!

techs-sus

@techs-sus

Joined June 1st, 2026

  • 37Devlogs
  • 1Projects
  • 1Ships
  • 20Votes
Open comments for this post

2h 46m 3s logged

I watched a Kotlin talk about Flows and I was inspired to rewrite my program using them.

This made my program more efficient, idiomatic and also helped me fix the annoying progress bar refresh bug (multiple old bars shown). It also let me actually properly sort by position across all 4 status types (added, removed, moved, errored).

I also made the downloading functions use one underlying common function to clean up the codebase. I also removed sqlx4k because it wasn’t actually parallel and was causing issues with init.

Here, in the screenshot I am showing the new elegant code for the logging of track statuses. It used to be many individual async calls, but flows allow me to group them up and sort them.

0
0
17
Open comments for this post

33m 3s logged

I made position diffing aware of insertions and deletions, so that output is less bloated with useless move info such as 0->1, 1->2, etc.

I also did some optimization by using database transactions wherever possible. I can’t do it in the main sync body because it is bounded to its own coroutine scope.

0
0
11
Open comments for this post

21m 35s logged

I made it so that thumbnails should now be even higher quality, it does take more storage but the difference is quite noticeable on some music players.

Also small hotfix, if you accidentally pass in another unrelated SQLite database it will now not run migrations on it before erroring.

0
0
13
Open comments for this post

38m 55s logged

To help users migrate from the old Rust implementation, I made it so that a sync will re-tag the track if the track’s thumbnail does not exist on disk.

The Kotlin implementation always gets higher resolution images, so this allows for much higher resolution track covers.

0
0
34
Open comments for this post

1h 19m 21s logged

In my attempt to make the streamExtractor lazily loaded, I caused a deadlock. I have fixed the deadlock and this fixed version is at v0.2.7.

The fix was pretty simple, it was to not use CoroutineStart.Lazy because a lazy coroutine may never run, meaning the parent coroutineScope will hang forever.

I also switched the backend driver to sqlx4k as it provides a connection pool but more importantly makes the suspend code flow cleaner.

I wont switch to Exposed (the official SQL driver) because it doesn’t have the same parallel capabilities as sql4k.

0
0
27
Open comments for this post

1h 45m 35s logged

I forgot to add error handling from the original Rust project, so I did that.

I also fixed the parallelism by using a Semaphore as limitedParallelism still wakes all the coroutines. Using a Semaphore only allows N permits to be handed out at once. This means that only N tasks would be running at once, given that each task takes one permit. I set N to 8 as that should not cause any throttling but still allow multiple tracks to be downloaded at once.

I also implemented better lazy fetching than the old Rust implementation. Now only pieces that must be fetched are fetched, and if they don’t need to be fetched, a StreamExtractor is never fetched. This causes a huge speed up, allowing my ~400 track playlist to be incrementally synced in 8 seconds.

Other notable quality of life features (taken from the git log):

- refactor: make output use terminal.theme.*
- refactor: make output more human readable by using title instead of youtube_playlist_id
- fix: reorder items in subtasks so that the text doesn't move everything else
0
0
13
Open comments for this post

46m logged

Shortly after I shipped, I found a better library for progress bars and displaying to the terminal in general.

I also made sure that the exists locally log line would be printed out in order.

I decided to use it, and I am really happy with the result!!!!

0
0
43
Ship Pending review

I made a Kotlin CLI program that synchronizes a YouTube Music playlist to a SQLite database locally.

I made this because I want to be able to play my music freely even when YouTube Music or my network is down.

The main challenge was finding a library that would let me get the data I needed (artist, thumbnail, audio tracks, etc.) from YouTube Music, and I even had to rewrite the entire program in Kotlin from Rust because the library I was using couldn’t download audio properly.

  • 27 devlogs
  • 45h
Try project → See source code →
Open comments for this post

1h 13m 29s logged

Preparing to ship the project, so here’s a list of everything I did:

  • added back an edited readme
  • added back the apache 2.0 license
  • fixed the github actions auto release
  • recorded an asciinema cast and put it in the readme
  • made the cli say music-player-kotlin instead of cli
  • …other small changes to make sure its ready for release
0
0
19
Open comments for this post

25m 43s logged

I fixed position tracking, so that moved tracks will output a line telling you they have moved.

I attempted to fix a deadlock that was happening, and fixed some database queries targetting the wrong table.

0
0
8
Open comments for this post

4h 9m 52s logged

the rewrite is almost finished

thumbnails are now way higher in resolution because we can now get youtube’s webp images. unfortunately jaudiotagger does not support webp images, so i force all images from youtube to turn into a lossless png

kotlin is pretty cool, especially coroutines, its like lua’s coroutines but actually backed by a thread pool

i need to limit the concurrency but otherwise this is great! very fast even on a debug build

what’s left:

  • currently unlimited concurrency, this will definitely crash the jvm on large playlists
  • better terminal output with colors and a diff generator
  • use a temporary table in sqlite to make diffing more memory efficient
  • packaging and ci should be fine since “java runs anywhere”
0
0
10
Open comments for this post

4h 22m 50s logged

i begun porting the project to kotlin

while i love rust i also want this project to actually work

rustypipe will always be a bit behind youtube’s protections so i decided to just rewrite the whole thing in kotlin so i can use newpipeextractor directly

what’s left:

  • tag audio with jaudiotagger
  • use clikt to make a nice command line interface
  • (maybe) add unit tests

there is no actual screenshot because i didn’t actually implement the commands yet

0
0
30
Open comments for this post

4h 19m 20s logged

i got rustypipe-botguard working with Nix

i still can’t figure out why some videos don’t work sometimes but other videos work all the time

i updated the test suite to reflect that

0
0
4
Open comments for this post

1h 3m 23s logged

i finally did the ci pipeline for windows, linux, and macos

i wrote a readme but i’ll need to add an asciinema cast to it to make it look better and allow me to ship the project

0
0
13
Open comments for this post

1h 35m 16s logged

thumbnails were really low quality, this change allows for higher quality thumbnails. one example would be 60x60 -> 120x120 still low quality but a higher low quality.

other notable changes:

  • unification of all track identifiers into one
  • refetch thumbnails if not existing & do not fetch thumbnail if its {id}.{png,jpeg,jpg} exist
  • m3a -> m3u, it is more compatible with music players (this happened in 4c337f491dd949fdc3f1f5d51363b0342defaac1 on aug 15, i forgot to log it)

next thing to do is packaging . this is my worst nightmare so the whole program will be statically linked

0
0
6
Loading more…

Followers

Loading…