In a couple of previous posts I have covered my NymphCast project [1] as well as my approach to testing a project before release [2]. As I noted in that second post, NymphCast is a hobby project, and one definition of a 'hobby' is an activity practiced in one's spare time for the sake of relaxation and enjoyment. Here it should be fairly obvious already that developing an ambitious software project from scratch by oneself would be an excellent example of balancing the fine line between 'enjoyment' and 'unpaid work'.
The past weeks I have made a couple of major changes to the project, moving the SDL-based video display and window-handling routines - including the screensaver element - as well as the entirety of the SDL initialisation to a single class. I also rewrote the SoundCloud app to use the new JSON responses from the SoundCloud backend, adding regular expression and key-value store (KVS) support to the AngelScript API to allow the SoundCloud app in NymphCast to fully work for searches and playback of tracks and albums.
After that first major change, I did notice a regression with the playback of files, with playback no longer stopping by itself after a track or video had finished. This persisted after making the second stack of changes, as noticed after trying to stream an album from SoundCloud, with only the first track playing. This finding led me to dive deep into the ffmpeg-based code, with the debugger backtraces as a guide, to figure out where things were going off the rails.
Sometimes there doesn't seem to be a particular reason why a regression like this happens. In those cases it's usually a case of the existing code (in this case heavily borrowed from ffmpeg's ffplay source) being fragile enough that a small change elsewhere or a timing change makes it fall over and catch on fire. Since I couldn't find a particular cause for this regression, I opted to instead improve the existing code to better detect the end-of-file condition once I felt that I had a solid enough grasp on how the code was interacting with the ffmpeg APIs.
It was at this point that I realised that the project was becoming more my 'work' than my actual work, with it consuming a significant part of each day for the past weeks. More seriously, I wasn't enjoying myself. Though I knew that more tests needed to be run, with the goal of finding more issues that need fixing, it's clear that none of this is really 'fun', and more something that one does because it has to be done. Not to say that hobbies do not have those moments where one has to work through something unpleasant, but the difference between a job and hobby should be that with the latter one volunteers to do the work when one feels like it.
Thus I choose to just push the presumed fix to Github and leave it like that for now.
It feels good to do a bit of recharging after a bit too much 'hobby' work like that. To instead think about some small aspects that one could do at some point in the future when one again relishes a challenge to sink one's fangs into. Until then there are other hobbies and of course paid work to spend time on. The last thing one wants is to burn out on a hobby project.
Some other issues have also popped up over the past months that take the fun out of the project. Take for example the idea of using the same client-side application (NymphCast Player) for desktop and mobile. This ran into a breaking bug in Qt's Android support [3]. After considering writing a native Android client (in Java with NDK-based C++ core), the additional work of getting back into Android development didn't feel extremely appealing. The last time I did Android development, the ADT-based Eclipse IDE was still the cat's pyjama's, and I still haven't come to terms with this newfangled Android Studio thing. Basically there is no fun to be found in that direction either. At least not right now.
I still like the NymphCast project as a whole, and I have noticed that others do too, from the stack of Github tickets where people express their gratitude for the project, as well as a couple of small donations for the project. Yet as a whole, the project is still in this awkward phase where it's supposed to be 'fun' because it's a hobby project while at the same time there exist these external expectations about the project and what it could become.
For the immediate future, I'm still immensely grateful for any Github issue tickets for things that I wouldn't have (easily) found myself, as well as the emotional boost from the donations. It's just a matter of time when I'll feel like grinding through the rest of this debugging and testing, much like how one would get through the less fun parts of a video game.
Maya
[1] https://mayaposch.blogspot.com/2020/03/nymphcast-casual-attempt-at-open.html
[2] https://mayaposch.blogspot.com/2020/03/the-fickle-world-of-software-development.html
[3] https://bugreports.qt.io/browse/QTBUG-83372
Showing posts with label nymphcast. Show all posts
Showing posts with label nymphcast. Show all posts
Monday, 11 May 2020
Friday, 27 March 2020
The fickle world of software development
At the beginning of this month, I published a blog post titled 'NymphCast: A casual attempt at an open alternative to ChromeCast and kin' [1]. This got picked up a number of tech websites [2][3][4][5][6] over the past weeks. Explaining to people just what the NymphCast project [7] is about, what it can do right now and perhaps most importantly getting feedback about how people perceive the project based on the information that is out there right now, all of that has been quite enlightening.
As I wrote that original blog post, I was still in the process of finishing up the implementation of the basic features of the initial (v0.1) release. Meaning that it was a definite prototype, with the scaffolding obscuring much of what was already there, but also what wasn't there yet. Things like seeking through files being streamed, for example. Essentially with the way the project got presented in those articles, it sounded as if it was a ready to use solution folk could just slap onto their Raspberry Pi compute things and be off to the races.
Suffice it to say that this caused a bit of confusion in the commentary to those articles.
I have since put a product page with documentation [8] over at the Nyanko website, with information on how to develop these mysterious 'NymphCast apps' using the AngelScript programming language. That partially addresses the point of where in blazen's name the documentation for any of it is. The other points raised were about its feature set and what it will support in the future, as well as a host of related questions.
The tricky thing there is that as I had formulated it in my blog post, the project is first and foremost a fun hobby project of mine to scratch this itch of there not being a proper open source, cross-platform solution that is like ChromeCast or AirPlay. Of course I am open to extending the feature set to add things that do not necessarily scratch my own itches. A lot of features that got suggested are interesting from a development and technical point of view, so I see them as interesting challenges to learn from and grow as a developer.
Yet things are never quite that rosy.
Even though I implemented the last and most invasive feature into NymphCast a few weeks ago (full seeking support), this only meant that the rule of thumb that I use for estimating required development time kicked in. This rule is the '10/90/90' rule, as in the workload in any (software) project is 10% planning, 90% implementing (100%, or what usually gets scheduled) and 90% testing/debugging (making a total of 190%, for those keeping score). A rough estimate on development time for NymphCast is that I spent about a month (full-time) on it. This means that with testing time having kicked in, I'll have a few (full-time) weeks of testing ahead of me, including the Alpha, Beta and Release Candidate phases.
Here of course one can cheat, as is common in (commercial) software development; instead of accepting the 10/90/90 rule, it gets instead crammed into something like '10/90/10', with just enough testing done that nothing is all too obviously broken for the first users. This often leads to the other 80% of testing being combined into subsequent development cycles. If I were to follow this approach, the v0.2 development version of NymphCast would involve a lot of catching up on bugs and issues that lived on due to the shortened v0.1 test cycle.
It's quite possible that these latent bugs and issues from v0.1 would interfere with v0.2 development, even slowing it down, as it would often be unclear whether a new feature or change created a regression, or whether one merely tripped over a hidden bug. This is why I'm no big fan of shortened test cycles. Of course, this does mean that you end up disappointing end-users (or heavens forbid, customers). Instead, I prefer to just grind my way through testing, torturing the software using countless (intended and unintended) usage scenarios to shake out bugs. Let me just say that I fixed a whole stack of issues between the first (alpha1) and second (alpha2) alpha releases.
Here of course the consideration is that end-users ultimately want to have something that Just Works (tm), with only a certain tolerance for bugs and issues. Is having them wait longer worse than giving them a broken product?
All of this is more or less a long-winded way to say that the rush of popularity (nearly 50,000 views on that one blog post, and over 1,100 stars on the Github project) was unexpected and perhaps somewhat premature. Possibly.
Though I very much appreciate the attention, it does put me into a bit of a pickle. On one hand there's now this sudden popularity, that will likely die down if the project doesn't deliver, yet going into full-time development mode to get the v0.1 release and beyond out of the door isn't feasible either. It's, after all, a hobby project. Hobby projects do not pay the bills, or put food on the table.
It seems almost as if the only real option is to let the project slip back into obscurity, while I slowly work away on it over the next months and perhaps years, until it's ready(-ish) for prime time.
Time will tell, I guess.
Maya
[1] https://mayaposch.blogspot.com/2020/03/nymphcast-casual-attempt-at-open.html
[2] https://tweakers.net/geek/164126/ontwikkelaar-maakt-open-source-chromecast-alternatief.html
[3] https://www.reddit.com/r/linux/comments/fhdnav/nymphcast_an_opensource_alternative_to_chromecast/
[4] https://www.tomshardware.com/news/using-raspberry-pi-like-a-chromecast-open-source-nymphcast-project-makes-it-happen
[5] https://www.kitguru.net/lifestyle/mobile/accessories/christopher-nohall/nymphcast-turns-your-raspberry-pi-into-a-streaming-device/
[6] https://news.ycombinator.com/item?id=22457351
[7] https://github.com/MayaPosch/NymphCast
[8] http://nyanko.ws/nymphcast.php
As I wrote that original blog post, I was still in the process of finishing up the implementation of the basic features of the initial (v0.1) release. Meaning that it was a definite prototype, with the scaffolding obscuring much of what was already there, but also what wasn't there yet. Things like seeking through files being streamed, for example. Essentially with the way the project got presented in those articles, it sounded as if it was a ready to use solution folk could just slap onto their Raspberry Pi compute things and be off to the races.
Suffice it to say that this caused a bit of confusion in the commentary to those articles.
I have since put a product page with documentation [8] over at the Nyanko website, with information on how to develop these mysterious 'NymphCast apps' using the AngelScript programming language. That partially addresses the point of where in blazen's name the documentation for any of it is. The other points raised were about its feature set and what it will support in the future, as well as a host of related questions.
The tricky thing there is that as I had formulated it in my blog post, the project is first and foremost a fun hobby project of mine to scratch this itch of there not being a proper open source, cross-platform solution that is like ChromeCast or AirPlay. Of course I am open to extending the feature set to add things that do not necessarily scratch my own itches. A lot of features that got suggested are interesting from a development and technical point of view, so I see them as interesting challenges to learn from and grow as a developer.
Yet things are never quite that rosy.
Even though I implemented the last and most invasive feature into NymphCast a few weeks ago (full seeking support), this only meant that the rule of thumb that I use for estimating required development time kicked in. This rule is the '10/90/90' rule, as in the workload in any (software) project is 10% planning, 90% implementing (100%, or what usually gets scheduled) and 90% testing/debugging (making a total of 190%, for those keeping score). A rough estimate on development time for NymphCast is that I spent about a month (full-time) on it. This means that with testing time having kicked in, I'll have a few (full-time) weeks of testing ahead of me, including the Alpha, Beta and Release Candidate phases.
Here of course one can cheat, as is common in (commercial) software development; instead of accepting the 10/90/90 rule, it gets instead crammed into something like '10/90/10', with just enough testing done that nothing is all too obviously broken for the first users. This often leads to the other 80% of testing being combined into subsequent development cycles. If I were to follow this approach, the v0.2 development version of NymphCast would involve a lot of catching up on bugs and issues that lived on due to the shortened v0.1 test cycle.
It's quite possible that these latent bugs and issues from v0.1 would interfere with v0.2 development, even slowing it down, as it would often be unclear whether a new feature or change created a regression, or whether one merely tripped over a hidden bug. This is why I'm no big fan of shortened test cycles. Of course, this does mean that you end up disappointing end-users (or heavens forbid, customers). Instead, I prefer to just grind my way through testing, torturing the software using countless (intended and unintended) usage scenarios to shake out bugs. Let me just say that I fixed a whole stack of issues between the first (alpha1) and second (alpha2) alpha releases.
Here of course the consideration is that end-users ultimately want to have something that Just Works (tm), with only a certain tolerance for bugs and issues. Is having them wait longer worse than giving them a broken product?
All of this is more or less a long-winded way to say that the rush of popularity (nearly 50,000 views on that one blog post, and over 1,100 stars on the Github project) was unexpected and perhaps somewhat premature. Possibly.
Though I very much appreciate the attention, it does put me into a bit of a pickle. On one hand there's now this sudden popularity, that will likely die down if the project doesn't deliver, yet going into full-time development mode to get the v0.1 release and beyond out of the door isn't feasible either. It's, after all, a hobby project. Hobby projects do not pay the bills, or put food on the table.
It seems almost as if the only real option is to let the project slip back into obscurity, while I slowly work away on it over the next months and perhaps years, until it's ready(-ish) for prime time.
Time will tell, I guess.
Maya
[1] https://mayaposch.blogspot.com/2020/03/nymphcast-casual-attempt-at-open.html
[2] https://tweakers.net/geek/164126/ontwikkelaar-maakt-open-source-chromecast-alternatief.html
[3] https://www.reddit.com/r/linux/comments/fhdnav/nymphcast_an_opensource_alternative_to_chromecast/
[4] https://www.tomshardware.com/news/using-raspberry-pi-like-a-chromecast-open-source-nymphcast-project-makes-it-happen
[5] https://www.kitguru.net/lifestyle/mobile/accessories/christopher-nohall/nymphcast-turns-your-raspberry-pi-into-a-streaming-device/
[6] https://news.ycombinator.com/item?id=22457351
[7] https://github.com/MayaPosch/NymphCast
[8] http://nyanko.ws/nymphcast.php
Sunday, 1 March 2020
NymphCast: a casual attempt at an open alternative to ChromeCast and kin
For the past half year or thereabouts I have been working on a little project of mine that I call 'NymphCast' [1]. The initial idea for it originated at the beginning of 2019, when I found myself perplexed at the usability and compatibility issues that exist with streaming solutions like ChromeCast (Google proprietary) and AirPlay (Apple proprietary). Also how this was not improved much with PulseAudio (Linux-exclusive). It should be possible to have an open standard that would just work on any platform for streaming audio and video across a network.
First step was scraping together existing software solutions for handling the boring parts like shovelling bytes across the network and decoding and playing back audio and video. For the network communication part between server and client I was happy to use my own NymphRPC [2] remote procedure call library, as this provided the required functionality to transfer data between client and server in a light-weight library, which I also know to have been used in production environments. For the video and audio decoding, and the playback I settled on Ffmpeg [3] with LibSDL [4]. I also tried the gstreamer and LibVLC libraries, but could not make either of them work for the project.
It's interesting to essentially rebuild an existing system. The requirements for NymphCast were rather obvious: same as for ChromeCast, Roku and Amazon's dongle. That 'just' left implementing it. Playing back audio and video from a memory buffer and keeping that memory buffer filled while also allowing for efficient seek operations on the remote file gives one a lot of insight in where the bottlenecks lie on a computer and a network, but is mostly tedious work. Most of the work probably went into the other aspect of ChromeCast and kin: custom apps that add functionality, such as streaming from online services like YouTube, Netflix and SoundCloud.
Since ChromeCast's server solution (what runs on a ChromeCast dongle) is essentially a Chrome browser instance, these ChromeCast apps are simply HTML pages with JavaScript that get loaded from a remote server. Because NymphCast is a native C++ application it's free to use whatever approach it wants for NymphCast apps. Here I wanted a scripting language that's easy to integrate with C++ and both easy and powerful enough to be used for whatever such a custom app might require. Having embedded both Lua and Python in the past, I wanted something less clunky and ideally statically typed, which led me to AngelScript [5].
AngelScript has essentially C++ syntax and supports most C++ concepts directly, allowing it to be embedded in a C++ application without any jumping through hoops and with no overhead. What it also shares with C++ is that it is statically typed, meaning that when the script file is compiled, the AngelScript compiler will perform type and syntax checks, informing you where you made a mistake instead of the runtime throwing an error and bailing out while the app is running. I really appreciated this feature while developing the SoundCloud demonstration app.
As an aside, people have asked me over the past months why I didn't just implement the AirPlay or ChromeCast protocols (both of which have been more or less reverse engineered). The primary reason is that both are proprietary protocols which have been altered by the companies behind them and very likely will be changed again in the future. There is also limited use in supporting those protocols, as one isn't simply going to support ChromeCast apps or such, as these have been cryptographically locked away so unless you'll crack those AES or similar keys, it'd be at best a half-hearted kludge and a worst a massive waste of time and effort.
Considering that I managed to implement a basic SoundCloud NymphCast app within an hour using the public (HTTP) API, it would seem to me that it would be a more productive approach to get NymphCast into a state where I could contact SoundCloud and similar companies on whether they'd want to produce an official NymphCast app (hosted on their own servers) and thus get NymphCast on a level playing field with the competition, rather than acting like a trojan and constantly having to fix things whenever Google or Apple change something on their end. That's not the kind of 'competing' which I am into.
This leads me to the current state of NymphCast: I have used the NymphCast server on Windows, Linux x86 and Linux ARM on Raspberry Pi SBCs and other ARM-based SBCs. The client runs on all desktop platforms and on Android (Qt-based). While I would definitely call it Alpha-level software, with some features such as seeking support still being implemented, I am rapidly running out of missing features to implement. Leaving seeking support as one of the final features to implement for the first release was mostly because it is less essential than stabilising the other features.
One interesting thing which I have found during testing is that even if one were to never want to skip through an audio track or film, seeking support is still needed, as the MP4 container format for one has this nice feature where by default it puts the 'header' with the container details at the end of the file. This means that the player has to first seek to the end of the file, read the 'header', set the configuration, seek back to the file beginning and then start playing.
All taken together, this seeking support and some functions to get real-time playback information in the client are the only things that still need to be implemented before the first NymphCast release goes into Beta, meaning the shaking out of bugs and any other issues that may pop up during testing. Here I want to make it as easy as possible for people to help with testing, by providing an easy way to get NymphCast on a few supported platforms, such as the Raspberry Pi for the server, and for the client desktop platforms as well as Android devices. Compiling the client for iOS smartphones is harder, as this requires one to have a Mac system, which I do not, but this can be solved as well.
So what is it that I want to accomplish with NymphCast? Most of all to have a nice platform that I can use myself for streaming audio and video to any (powered) speakers and displays that I have standing around, along with the extensibility offered by NymphCast apps. I also hope that others will start using it, even adding NymphCast support to their (smartphone) apps. It would be wonderful to see private companies embrace it and release official apps that would allow people to use their services from NymphCast, cutting out proprietary ChromeCast, Airplay, Sonos and various SmartTV platforms.
The open nature of NymphCast (3-clause BSD licenced) is one big benefit, but also the ability to install the server on any Raspberry Pi board or equivalent without any hardware devices having to be produced, shipped, purchased and eventually tossed away, like the dongles for Google and Amazon's solutions, or entire speakers and devices as in the case of Sonos and Roku. NymphCast will work with any general purpose system, whether it is a Raspberry Pi, OrangePi, Intel NUC, some AMD APU-based board or a full-blown gaming PC.
Call me nuts, but I think that it might just be crazy enough to work.
Maya
[1] https://github.com/MayaPosch/NymphCast
[2] https://github.com/MayaPosch/NymphRPC
[3] http://www.ffmpeg.org/
[4] http://www.libsdl.org/
[5] http://www.angelcode.com/angelscript/
[6] https://github.com/MayaPosch/NymphCast/blob/master/src/server/apps/soundcloud/soundcloud.as
First step was scraping together existing software solutions for handling the boring parts like shovelling bytes across the network and decoding and playing back audio and video. For the network communication part between server and client I was happy to use my own NymphRPC [2] remote procedure call library, as this provided the required functionality to transfer data between client and server in a light-weight library, which I also know to have been used in production environments. For the video and audio decoding, and the playback I settled on Ffmpeg [3] with LibSDL [4]. I also tried the gstreamer and LibVLC libraries, but could not make either of them work for the project.
It's interesting to essentially rebuild an existing system. The requirements for NymphCast were rather obvious: same as for ChromeCast, Roku and Amazon's dongle. That 'just' left implementing it. Playing back audio and video from a memory buffer and keeping that memory buffer filled while also allowing for efficient seek operations on the remote file gives one a lot of insight in where the bottlenecks lie on a computer and a network, but is mostly tedious work. Most of the work probably went into the other aspect of ChromeCast and kin: custom apps that add functionality, such as streaming from online services like YouTube, Netflix and SoundCloud.
Since ChromeCast's server solution (what runs on a ChromeCast dongle) is essentially a Chrome browser instance, these ChromeCast apps are simply HTML pages with JavaScript that get loaded from a remote server. Because NymphCast is a native C++ application it's free to use whatever approach it wants for NymphCast apps. Here I wanted a scripting language that's easy to integrate with C++ and both easy and powerful enough to be used for whatever such a custom app might require. Having embedded both Lua and Python in the past, I wanted something less clunky and ideally statically typed, which led me to AngelScript [5].
AngelScript has essentially C++ syntax and supports most C++ concepts directly, allowing it to be embedded in a C++ application without any jumping through hoops and with no overhead. What it also shares with C++ is that it is statically typed, meaning that when the script file is compiled, the AngelScript compiler will perform type and syntax checks, informing you where you made a mistake instead of the runtime throwing an error and bailing out while the app is running. I really appreciated this feature while developing the SoundCloud demonstration app.
As an aside, people have asked me over the past months why I didn't just implement the AirPlay or ChromeCast protocols (both of which have been more or less reverse engineered). The primary reason is that both are proprietary protocols which have been altered by the companies behind them and very likely will be changed again in the future. There is also limited use in supporting those protocols, as one isn't simply going to support ChromeCast apps or such, as these have been cryptographically locked away so unless you'll crack those AES or similar keys, it'd be at best a half-hearted kludge and a worst a massive waste of time and effort.
Considering that I managed to implement a basic SoundCloud NymphCast app within an hour using the public (HTTP) API, it would seem to me that it would be a more productive approach to get NymphCast into a state where I could contact SoundCloud and similar companies on whether they'd want to produce an official NymphCast app (hosted on their own servers) and thus get NymphCast on a level playing field with the competition, rather than acting like a trojan and constantly having to fix things whenever Google or Apple change something on their end. That's not the kind of 'competing' which I am into.
This leads me to the current state of NymphCast: I have used the NymphCast server on Windows, Linux x86 and Linux ARM on Raspberry Pi SBCs and other ARM-based SBCs. The client runs on all desktop platforms and on Android (Qt-based). While I would definitely call it Alpha-level software, with some features such as seeking support still being implemented, I am rapidly running out of missing features to implement. Leaving seeking support as one of the final features to implement for the first release was mostly because it is less essential than stabilising the other features.
One interesting thing which I have found during testing is that even if one were to never want to skip through an audio track or film, seeking support is still needed, as the MP4 container format for one has this nice feature where by default it puts the 'header' with the container details at the end of the file. This means that the player has to first seek to the end of the file, read the 'header', set the configuration, seek back to the file beginning and then start playing.
All taken together, this seeking support and some functions to get real-time playback information in the client are the only things that still need to be implemented before the first NymphCast release goes into Beta, meaning the shaking out of bugs and any other issues that may pop up during testing. Here I want to make it as easy as possible for people to help with testing, by providing an easy way to get NymphCast on a few supported platforms, such as the Raspberry Pi for the server, and for the client desktop platforms as well as Android devices. Compiling the client for iOS smartphones is harder, as this requires one to have a Mac system, which I do not, but this can be solved as well.
So what is it that I want to accomplish with NymphCast? Most of all to have a nice platform that I can use myself for streaming audio and video to any (powered) speakers and displays that I have standing around, along with the extensibility offered by NymphCast apps. I also hope that others will start using it, even adding NymphCast support to their (smartphone) apps. It would be wonderful to see private companies embrace it and release official apps that would allow people to use their services from NymphCast, cutting out proprietary ChromeCast, Airplay, Sonos and various SmartTV platforms.
The open nature of NymphCast (3-clause BSD licenced) is one big benefit, but also the ability to install the server on any Raspberry Pi board or equivalent without any hardware devices having to be produced, shipped, purchased and eventually tossed away, like the dongles for Google and Amazon's solutions, or entire speakers and devices as in the case of Sonos and Roku. NymphCast will work with any general purpose system, whether it is a Raspberry Pi, OrangePi, Intel NUC, some AMD APU-based board or a full-blown gaming PC.
Call me nuts, but I think that it might just be crazy enough to work.
Maya
[1] https://github.com/MayaPosch/NymphCast
[2] https://github.com/MayaPosch/NymphRPC
[3] http://www.ffmpeg.org/
[4] http://www.libsdl.org/
[5] http://www.angelcode.com/angelscript/
[6] https://github.com/MayaPosch/NymphCast/blob/master/src/server/apps/soundcloud/soundcloud.as
Subscribe to:
Comments (Atom)