~hristoast/hristoast

hristoast/site/mousikofidi-my-music-cloud.html -rw-r--r-- 9.5 KiB
27ec638fHristos N. Triantafillou Typo a day ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
<h1 id="title">MousikóFídi: My Music Cloud</h1>

<div id="dates">
  <span>Posted: <time id="post-date">2020-10-31</time></span>
</div>

<p id="post-excerpt">
  A web application that will serve audio and video files over HTTP, and is usable on viewports of all sizes. <a href="https://mousikofidi.info/">MousikóFídi</a> is something I made for myself, but it is dedicated to all music-lovers of the world. Read on to find out more about what it is, and why I made it.
</p>

<div id="toc"></div>

<h3>What, Now?</h3>

<p>
  If you're not familiar, I'm talking about a music and video player that works in your web browser! The software runs on some server, be it a local machine where your collection lives or something else, and any device with a modern web browser can open a URL and begin enjoying audio and/or video. <span class="footnote"> By "modern", I mean having usable <code>&lt;audio&gt;</code> and <code>&lt;video&gt;</code> elements and supporting newer ECMAScript features.</span>
</p>

<p>
  MousikoFidi is such a web-based music player that can load your collection from a directory structure automatically, without any need for a database, and it has a responsive user interface that looks great on mobile devices.
</p>

<h3>Why?</h3>

<p>
  I had been a user of <a href="http://ampache.org/">Ampache</a> since around 2009; I just loved the idea of streaming my personal collection through a web browser! I would continue to use Ampache for nearly ten more years, it served me well and continues to be great software.
</p>

<p>
  The initial urge to make "an Ampache clone" came after reading <a href="https://drewdevault.com/2019/01/30/Why-I-built-sr.ht-with-Flask.html">Drew DeVault talk about using Flask to make Sourcehut</a>. <span class="footnote"> As I understand it, at least a few of those components have since been rewritten in golang!</span> I was no stranger to web development with Python, but I never really made a "real" application with Flask. I'd used Django quite a bit, as well as a bit of Bottle.py, but no Flask.
</p>

<p>
  A little over two years ago, I began cycling regularly. I often liked to listen to music on my phone as it was strapped to my arm, speaker pointed towards my head. Who doesn't love some nice tunes during a workout? Of course it struck me to use Ampache during these rides, via <a href="https://www.f-droid.org/en/packages/com.antoniotari.reactiveampacheapp/">the Power Ampache app for Android</a>.
</p>

<p>
  For whatever reason, I would have consistent issues with Power Ampache not continuing playback when a track ended. It was bad enough that I stopped using it altogether, choosing instead to load up my device with audio files from my collection. This worked fine for a while but is inflexible for someone like me who doesn't have any Google "apps" or any connection to "the cloud" from my device; I have to connect my device via USB, and use <code>adb</code> from my computer to move files onto the device. <span class="footnote"> For the curious: I'm using <a href="https://lineageos.org/">LineageOS</a> with <a href="https://f-droid.org/">FDroid</a> as my only source for software. No Google, no way!</span>
</p>

<h3>Do It Yourself</h3>

<p>
  Faced with this, I did what most folks probably wouldn't do: I decided I wanted to write my own web-based music player application. But I wouldn't actually start work on MousikóFídi for almost another year.
</p>

<p>
  When I finally did begin work, I had taken a few weeks off from my day job but made no specific plans. That morphed into "hack furiously on some Javascript and Python", though! Within a few weeks I'd have a reasonably usable prototype, and it would finally dawn on me just how much more work was ahead of me to get things really fleshed out.
</p>

<p>
  I had a few specific goals in mind for the "base functionality" of MousikóFídi:
</p>

<ul>
  <li>Play my collection through a web browser. I wanted browsing my collection to feel like I'm just browsing folders on my filesystem, since it's already highly organized.</li>
  <li>Leverage the built-in <code>&lt;audio&gt;</code> and <code>&lt;video&gt;</code> elements to handle playback.</li>
  <li>A relational (or no sql) database is not reqiured; MousikóFídi should just be pointed at some directories and read files within.</li>
  <li>Simple installation; similar softwares have complex installation and setup processes. MousikóFídi can be ran and viewed immediately after installation <a href="https://mousikofidi.info/setup/#quickstart">with one command</a>. <span class="footnote"> Running it in <a href="https://mousikofidi.info/setup/#configuring-uwsgi">"production mode"</a> is also arguably more simple than with similar software; the Nginx config is little more than a <code>proxy_pass</code> definition.</span></li>
  <li>All "Vanilla Javascript;" this may sound crazy to some, but it actually has been the most enjoyable part of the project for me. I've learned just how powerful Javascript can be without any frameworks or extra stuff. Yes, I've had to reinvent the wheel here and there, but overall the effort does benefit the project in more ways than just a small page size! <span class="footnote"> Noteably, many things that are syntactically concise when using for example, jQuery, are a bit (to a lot) more involved. Also, coming up with a crude but simple method for stopping asynchronous functions mid-execution was a fun bit of research. <a href="https://stackoverflow.com/a/37642079">For the curious</a>.</span></li>
  <li>Be "fast;" of course, reading files on demand with no caching does take time. If you open a page with 200+ files, it could take up to several seconds to fully load. From my perspective this is an acceptible performance cost, and down the road MousikóFídi can be extended in ways that would alleviate or eliminate this performance bottleneck (see <a href="#the-future">below</a>). But all of that considered, MousikóFídi is pretty fast with a small base page size.</li>
  <li>The UI should properly scale on different-sized viewports; other similar softwares all require an "app" to be usable on mobile devices and the like. MousikóFídi's user interface will adjust as needed and still look good, even on devices with small screens.</li>
</ul>

<p>
  I didn't actually plan all of this from the start, though. It all sort of began with me implementing things that just felt or seemed right ("furiously hacking", as I mentioned before). <span class="footnote"> Nowadays I do keep an <a href="https://www.orgroam.com/">org-roam</a> document with my notes for MousikóFídi; I've got development plans for all the way out to version 4.0!</span>
</p>

<h3>What Can It Do?</h3>

<p>
  If you've read this far, you deserve some explanation of what MousikóFídi can actually do. Here's a quick run-down of features I didn't already go over:
</p>

<ul>
  <li><a href="https://developer.mozilla.org/en-US/docs/Web/Progressive_web_apps">PWA</a> Support; <a href="https://mousikofidi.info/user_guide/#mousik--f--di-as-a-pwa">install MousikóFídi like an "app"</a>! Offline mode is not supported. <span class="footnote"> A huge thank-you to Cadence on Sourcehut for suggesting this feature!</span></li>
  <li><a href="https://mousikofidi.info/user_guide/#copy-link">Share links</a> to specific tracks at specific times.</li>
  <li><a href="https://mousikofidi.info/user_guide/#keyboard-controls">Keyboard controls</a> for the audio and video players.</li>
  <li><a href="https://mousikofidi.info/user_guide/#the-queue">Build playlists while browsing</a>, save them to a file and then load them from that file as needed.</li>
  <li>Click the "Now Playing:" title of a track on the player to jump to that track on the page.</li>
  <li><a href="https://mousikofidi.info/user_guide/#breadcrumb-links">Breadcrumb links</a> that focus the page based on where you clicked from, and more.</li>
  <li>And of course, it can play audio and video files from your collection!</li>
</ul>

<p>
  I wasn't specifically looking to match all functionality provided by other softwares like MousikóFídi right away, but I do want to close some functionality gaps where it makes sense.
</p>

<h3>The Future</h3>

<p>
  Of course you can always do more, and although with the coming "1.0" release I do consider the core of MousikóFídi to be "feature-complete," I'm looking forward to adding new functionality. This includes but is not limited to:
</p>

<ul>
  <li>Support more media types. My own collection is almost entirely FLAC and MP3, with a very small amount of OGG Vorbis files. It'd be good to add support for other media types as well.</li>
  <li>A plugins framework, to provide a nice API for extending MousikóFídi.</li>
  <li>Database support (via an optional plugin).</li>
  <li>User accounts (authentication, also via an optional plugin).</li>
  <li>A fully custom media player.</li>
  <li>Some kind of <a href="https://beets.io/">beets</a> plugin for scraping metadata (another optional plugin).</li>
  <li>A "dynamic" UI that doesn't actually reload the page while browsing, to allow for browsing while listening/viewing.</li>
  <li>Who knows what else. Have an idea? Found a bug? <a href="https://todo.sr.ht/~hristoast/mousikofidi">Submit an issue for it</a>!</li>
</ul>

<p>
  Want to try MousikóFídi? Please check out <a href="https://demo.mousikofidi.info/">the demo</a>!
</p>

<p>
  Last but not least: if you're interested in the development of MousikóFídi, please consider subscribing to <a href="https://lists.sr.ht/~hristoast/mousikofidi">the mailing list</a>.
</p>

<p>
  Thank you for reading!
</p>

<h3>Footnotes And References</h3>

<div id="footnotes"></div>