SerialBox, Part 1: Google Drive API, audio, and UTF-8

I’ve started work on a very simple music player app to play audio files hosted in Google drive. I’ve found one iPhone app that will do this, but it’s riddled with ads, and even worse, it crashes regularly (I reinstalled it 3 times before deleting it for good). I record a lot of unpublished music and like to listen to a lot of it passively while I do other things. I keep it all in Google drive, but you can’t make playlists, so you have to keep closing and re-opening files. Annoying.

Concept: upload audio files to Google drive. Open app. Enter name of containing folder in app. Press play, put phone to sleep, and all music in folder plays until all tracks have been played. Typical player features TBD, but I’m aiming low to begin with (something something under-promise, over-deliver). Following today’s success (we’ll get to it), the primary remaining technical challenge is: will a web app be able to continue playing when browser is minimized and/or phone is screen-locked? Interesting challenge, and I’m sure I’ll learn something about memory management and browsers.

Today’s success: I could not figure out why the file content returned by the Google drive client was not being read by the DOM Audio component. I kept getting DOMException: Failed to load because no supported source was found. Spent an annoying amount of time experimenting with local files and HTTP with no luck. Finally, I rubber duck texted a friend of mine. Seconds after I hit send I found this answer on SO. D’oh – the file content was arriving as UTF! Of course.

              const dataArr = Uint8Array.from(fileRes.body.split('').map((chr) => chr.charCodeAt(0)));

              const realFile = new File([dataArr], file.name, { type: file.mimeType });

              const track = new Audio(URL.createObjectURL(realFile));

The variable fileRes has a body property containing the file’s contents, returned because the alt=media parameter was provided on GET. I could see it was a string, and it was binary. I tried encode to base64 and back; sent the contents to the backend Node app, saved to the fs and tried playing with a media player. No luck. The issue of course is the first line of code above: fileRes.body is a UTF-8 string representation of the binary data, not the binary data itself. So when I “saw” that it was binary, I really saw the UTF representation of the binary. Hence, decode each character literal, fill a typed integer array with the dereferenced actual numeric binary values the UTF-8 code values represent (and represent quite well, I might add), all in order to reconstruct the actual audio file, recognizable by the Audio component.

Software development is the art of analyzing what you take for granted. Something I learned fairly early on in my journey was, the “harder” the problem (that is, the more seemingly un-self-serviceable), the simpler the solution. Sometimes you really do need to unplug and plug back in.


Posted

in

by

Tags: