Closed vicwomg closed 11 months ago
This sounds like an excellent move, although I'm a bit concerned about that third Con bullet (about pi hardware limitations). Would that problem for a pi go away if the pitch-change was not used (or configurably disabled), or is the process-hog more inherent in ffmpeg? Alternatively, would a pi5 have the necessary grunt? If so, we each just need to wait for our pre-orders to be fulfilled before we make the jump (the race is ON!)
Wow, glad to hear this project is still going strong. Would love to see how this would be implemented.
This sounds like an excellent move, although I'm a bit concerned about that third Con bullet (about pi hardware limitations). Would that problem for a pi go away if the pitch-change was not used (or configurably disabled), or is the process-hog more inherent in ffmpeg? Alternatively, would a pi5 have the necessary grunt? If so, we each just need to wait for our pre-orders to be fulfilled before we make the jump (the race is ON!)
I have a proof of concept going now. Seems to work on OSX. I can't imagine ffmpeg is much more CPU-intensive with rendering and pitch-shift algorithms than VLC but I could be wrong. I think they use the same codecs under the hood.
Wow, glad to hear this project is still going strong. Would love to see how this would be implemented.
Haha well if by "going strong" you mean I update it once a year when I'm home for the holidays and bored.
This sounds like an excellent move, although I'm a bit concerned about that third Con bullet (about pi hardware limitations). Would that problem for a pi go away if the pitch-change was not used (or configurably disabled), or is the process-hog more inherent in ffmpeg? Alternatively, would a pi5 have the necessary grunt? If so, we each just need to wait for our pre-orders to be fulfilled before we make the jump (the race is ON!)
I have a proof of concept going now. Seems to work on OSX. I can't imagine ffmpeg is much more CPU-intensive with rendering and pitch-shift algorithms than VLC but I could be wrong. I think they use the same codecs under the hood.
Wow, glad to hear this project is still going strong. Would love to see how this would be implemented.
Haha well if by "going strong" you mean I update it once a year when I'm home for the holidays and bored.
Hahah, I constantly check this for updates. I love using pikaraoke so I'm super invested in seeing new stuff! Is your POC something you could share via PR? How do you plan on displaying the web browser on the display?
Proof of concept in the following branch 277-html_ffmpeg_video_rendering
I'm feeling really good about this direction. Interested in early feedback:
cd to your pikaraoke
git pull
git checkout 277-html_ffmpeg_video_rendering
pip3 install requirements.txt
You need ffmpeg and chrome installed. And if on pi, you need to be running a pi desktop UI
python3 app.py
Should launch a Chrome full-screen browser view using selenium. mp3/cdg and non-mp4 formats probably aren't working yet.
Note that the splash screen is hosted on: /splash , technically you could load it from any other computer and get the video streamed to it! Also like that it leaves so much to the WIndow OS. I have a feeling this will also address a lot of folks' issues with A/V support (bluetooth, external microphones, multiple screens, etc)
Raspberry pi 4 notes, lots of gotchas:
apt-get install python3-<module>
sudo apt-get install chromium-chromedriver
Raspberry pi 4 notes, lots of gotchas:
It ultimately works! You can host a server on it and stream the splash screen and videos remotely
The dependencies are waay easier now. They pull down in a couple of minutes.
ffmpeg video encoding is slow by default, fixed by specifying vcodec=copy. For other formats transcoding to mp4, it might also be acceleratable with h264 codecs enabled: https://stackoverflow.com/questions/40175644/ffmpeg-hardware-acceleration-on-raspberry-pi
The default download directory should change, desktop does not have access to the old directory without sudo
Python has trouble installing requirements.txt in desktop environment "This environment is externally managed". We might have to use venv which I did (blech). Or install them with a script and
apt-get install python3-<module>
Installing and updating yt-dlp is a pain in the ass. Consider migrating this to the python library so it's just another dependency, and we're not doing all this shell hackery
We need to install chromium-chromedriver:
sudo apt-get install chromium-chromedriver
Chromium struggles to launch in kiosk mode with the now-default "Wayfire" window manager, need to switch to X11 in raspi-config > Advanced
I want to double check but what do you mean by 'server'? When I think of server I think of one instance having different sessions like a karaoke room scenario where there's different rooms connected to a server but each room has their own session. But for this scenario, do you mean pi karaoke is a server where any web browser can be used as video source?
I mean the latter. The video player no longer needs to be on the same host as the server.
But nothing would stop you from launching multiple instances of PiKaraoke on the same machine on different ports to suit the use case you’re describing.
-v
On Fri, Nov 24, 2023 at 12:13 PM frankchau93 @.***> wrote:
Raspberry pi 4 notes, lots of gotchas:
-
It ultimately works! You can host a server on it and stream the splash screen and videos remotely
The dependencies are waay easier now. They pull down in a couple of minutes.
ffmpeg video encoding is slow by default, fixed by specifying vcodec=copy. For other formats transcoding to mp4, it might also be acceleratable with h264 codecs enabled: https://stackoverflow.com/questions/40175644/ffmpeg-hardware-acceleration-on-raspberry-pi
The default download directory should change, desktop does not have access to the old directory without sudo
Python has trouble installing requirements.txt in desktop environment "This environment is externally managed". We might have to use venv which I did (blech). Or install them with a script and apt-get install python3-
Installing and updating yt-dlp is a pain in the ass. Consider migrating this to the python library so it's just another dependency, and we're not doing all this shell hackery
We need to install chromium-chromedriver: sudo apt-get install chromium-chromedriver
Chromium struggles to launch in kiosk mode with the now-default "Wayfire" window manager, need to switch to X11 in raspi-config > Advanced
I want to double check but what do you mean by 'server'? When I think of server I think of one instance having different sessions like a karaoke room scenario where there's different rooms connected to a server but each room has their own session. But for this scenario, do you mean pi karaoke is a server where any web browser can be used as video source?
— Reply to this email directly, view it on GitHub https://github.com/vicwomg/pikaraoke/issues/277#issuecomment-1826054802, or unsubscribe https://github.com/notifications/unsubscribe-auth/AA7KXNWFDSPTN4WLF5VQPEDYGD5WFAVCNFSM6AAAAAA7TVH2E6VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTQMRWGA2TIOBQGI . You are receiving this because you authored the thread.Message ID: @.***>
I mean the latter. The video player no longer needs to be on the same host
as the server.
But nothing would stop you from launching multiple instances of PiKaraoke
on the same machine on different ports to suit the use case you’re
describing.
-v
On Fri, Nov 24, 2023 at 12:13 PM frankchau93 @.***>
wrote:
Raspberry pi 4 notes, lots of gotchas:
-
It ultimately works! You can host a server on it and stream the splash
screen and videos remotely
-
The dependencies are waay easier now. They pull down in a couple of
minutes.
-
ffmpeg video encoding is slow by default, fixed by specifying
vcodec=copy. For other formats transcoding to mp4, it might also be
acceleratable with h264 codecs enabled:
https://stackoverflow.com/questions/40175644/ffmpeg-hardware-acceleration-on-raspberry-pi
-
The default download directory should change, desktop does not have
access to the old directory without sudo
-
Python has trouble installing requirements.txt in desktop environment
"This environment is externally managed". We might have to use venv which I
did (blech). Or install them with a script and apt-get install
python3-
-
Installing and updating yt-dlp is a pain in the ass. Consider
migrating this to the python library so it's just another dependency, and
we're not doing all this shell hackery
-
We need to install chromium-chromedriver: sudo apt-get install
chromium-chromedriver
-
Chromium struggles to launch in kiosk mode with the now-default
"Wayfire" window manager, need to switch to X11 in raspi-config > Advanced
I want to double check but what do you mean by 'server'? When I think of
server I think of one instance having different sessions like a karaoke
room scenario where there's different rooms connected to a server but each
room has their own session. But for this scenario, do you mean pi karaoke
is a server where any web browser can be used as video source?
—
Reply to this email directly, view it on GitHub
https://github.com/vicwomg/pikaraoke/issues/277#issuecomment-1826054802,
or unsubscribe
.
You are receiving this because you authored the thread.Message ID:
@.***>
That's actually a great idea! Thank you. I hope it can support CDG with this new method it looks promising. Now I'm thinking to myself for the future if it's possible to save it as a PWA on a TV app. Should def be possible as an https proxy. Thanks for the great idea!
This branch is in a stable state for testing. I have checked it out on a pi4 2gb and it works great and we're at feature parity (transposition, cdg+mp3, etc)
Would appreciate some eyes from someone on a pi3 w/ raspberry pi desktop.
I hope it can support CDG with this new method it looks promising. Now I'm thinking to myself for the future if it's possible to save it as a PWA on a TV app. Should def be possible as an https proxy. Thanks for the great idea!
I would love to see some folks try this. I don't know how TVs with browser support work, but hopefully they could access local LAN ip addresses. One complication, though, is that you need to interact with the browser once before it will allow videos to play. That's just a limitation in most browsers, to prevent obnoxious advertising. Currently when visiting /splash, pikaraoke will show an overlay modal explaining that, with a button to press to dismiss it. This serves as the interaction. Hopefully this is easy to do on TVs. The potential here is that you could just add pikaraoke a centralized pi server in your house, perhaps one that you use for other tasks like home automation. It doesn't need to be connected to the TV to work
Wow! Does this mean I can have different karaoke instance in every room in the house all from just one server? (Assuming that I have a Smart TV in each room)
Can you give me a step-by-step instruction on how install that on a fresh Rpi3?
@troy-lim Let me know if this does it. Basically you're going to check out the work-in-progress branch and run it:
cd ~
git clone https://github.com/vicwomg/pikaraoke.git
cd pikaraoke
git checkout 277-html_ffmpeg_video_rendering
./setup.sh
./pikaraoke.sh --hide-splash
The output will show a url http://<yourip>:5555/splash
. That's gonna be what you point your client at to show the splash screen / video player. You can put that URL into a browser on a separate machine, or on the pi, or on the TV (maybe? I don't know how well it's going to render it)
if you want to run the server and the player on the same pi, you'd run ./pikaraoke.sh
without --hide-splash. This will fire up a chromium browser, auto-dismiss the initial prompt, and render it full screen.
Thus far in testing, pi4 keeps up really well. Pi 3 struggles a bit with files that need to be transcoded (mp3 + cdg, non-mp4/webm videos). The transcoding actually isn't the bottleneck, it seems like playing full-screen video with hardware acceleration in a browser is not great on the pi 3, but if you're not hosting the splash screen on the same pi, maybe that's fine. Upping the gpu_mem or overclocking might help. Haven't had a chance to check.
Edit: Overclocking my Pi 3B to 1.3ghz actually seemed to help a lot with splash screen playback on the pi. I can still get some stutters under high-load circumstances, but most general use seems completely fine. Hopefully that means the 3B+ and beyond should have no trouble stock.
I tried it on a Raspberry Pi 3B. I'm running into issues where the app would crash on me. It would play a couple songs and my queue would just disappear. Here's my log. Keep in mind i'm using a service to start/stop pikaraoke and this is the script that it runs. I'm not sure why it's crashing. I'm using the latest raspbian os version but i'm not checking it through hdmi. just trying to use it as a server so i ran 2 instances
`#!/bin/bash
source /home/pi/pikaraoke/.venv/bin/activate
python3 /home/pi/pikaraoke/app.py --hide-splash -l10 --port 7010 >> /home/pi/pikaraoke.log 2>&1 & python3 /home/pi/pikaraoke/app.py --hide-splash -l10 --port 7011 >> /home/pi/pikaraoke1.log 2>&1 & ` pikaraoke.log
@frankchau93 Can you elaborate on how you're launching it as a service? The logs seem to indicate that the process is in some kind of restart loop (about every minute). So that would probably prevent it from keeping an active queue for very long if at all. You might want to try it by starting it ad-hoc on the command line and see if you have better luck.
I made a systemd service /etc/systemd/system/pikaraoke.service `[Unit] Description=Pikaraoke Service Wants=network-online.target After=network-online.target
[Service] Type=forking User=pi ExecStart=/home/pi/start_pikaraoke.sh Restart=on-failure
[Install] WantedBy=multi-user.target`
I will try it by itself and see if anything changes
Edit: I've started to instances of pikaraoke manually with the script i posted earlier and it's working. I played a few songs and it didnt crash. I did run into an issue where one of the instances was queued to play but the video never started and i had to skip it to continue. It only happened once though and i played at least 10 songs per instance and let it run
EDIT2: There was an instance where things would just stop playing and I'm unable to skip or do anything. I can add stuff to queue and clear it but nothing would play, it would just say "Up Next:
[2023-12-01 11:04:19] DEBUG: [FFMPEG] Metadata:
[2023-12-01 11:04:19] DEBUG: [FFMPEG] title : It Wasn't Me [SC Karaoke]
['Salt-N-Pepa - Push It [#Z Karaoke].mp3', 'Salt-N-Pepa - Push It [#Z Karaoke].cdg']
['Taylor Swift - Blank Space [#Z Karaoke].mp3', 'Taylor Swift - Blank Space [#Z Karaoke].cdg']
["Staind - It's Been Awhile [AMS Karaoke].mp3", "Staind - It's Been Awhile [AMS Karaoke].cdg"]
["Shaggy  & Ricardo Rikrok Ducent - It Wasn't Me [SC Karaoke].cdg", "Shaggy  & Ricardo Rikrok Ducent - It Wasn't Me [SC Karaoke].mp3"]
Traceback (most recent call last):
File "/home/pi/pikaraoke/app.py", line 901, in
Super useful output @frankchau93 , looks like it didn't recover well from a song with some weird unicode in it:
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xa0 in position 28: invalid start byte
Shaggy  & Ricardo Rikrok Ducent - It Wasn't Me [SC Karaoke].cdg", "Shaggy  & Ricardo Rikrok Ducent - It Wasn't Me [SC Karaoke].mp3"
I'll be sure to fix that. Python is really bad at unicode.
didn't get it to stream remotely, but opening chrome locally works well.
I love this new direction. Particularly because I was having issues getting it to compile on an Atari VCS running Elementary OS. I had the same issue on Linux Lite.
I still can't get this branch working on the VCS though. I can post the error if you want. However, the fact that this works with a browser though makes this possibly even better. Right now I have it running from OSX on my laptop but the browser is running on the VCS through chrome in kiosk mode. It works just fine (you just can't have 2 splashes running at once.)
One thing that could help with this would be adding a --headless
option that wouldn't try to open chrome and it would just give you the URL. I could probably just run it in a Docker container at that point and have a shortcut to open the browser (or I could autoboot it to it.)
( Also, keep up the good work.. I was thinking I needed to build something, but then found this ;) )
One thing that could help with this would be adding a --headless option that wouldn't try to open chrome and it would just give you the URL.
I just realized that this option already exists as --hide-splash-screen
Yes, but “—headless” is the better name I was struggling to come up with! I’ll add that as an alias.
Please do share what dependency issues you were having with those Linux distros.
On Tue, Dec 5, 2023 at 3:47 PM Nathan Palmer @.***> wrote:
One thing that could help with this would be adding a --headless option that wouldn't try to open chrome and it would just give you the URL.
I just realized that this option already exists as --hide-splash-screen
— Reply to this email directly, view it on GitHub https://github.com/vicwomg/pikaraoke/issues/277#issuecomment-1841810386, or unsubscribe https://github.com/notifications/unsubscribe-auth/AA7KXNQRKNQ7F6S6YEC62M3YH6XCBAVCNFSM6AAAAAA7TVH2E6VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTQNBRHAYTAMZYGY . You are receiving this because you authored the thread.Message ID: @.***>
Looks like it's not a dependency issue, but a runtime issue.
> python3 app.py
Traceback (most recent call last):
File "/home/nathan/pikaraoke/app.py", line 13, in <module>
import cherrypy
File "/home/linuxbrew/.linuxbrew/Cellar/python@3.11/3.11.2_1/lib/python3.11/site-packages/cherrypy/__init__.py", line 71, in <module>
from cherrypy import _cpdispatch as dispatch # noqa: F401
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/linuxbrew/.linuxbrew/Cellar/python@3.11/3.11.2_1/lib/python3.11/site-packages/cherrypy/_cpdispatch.py", line 214, in <module>
getargspec = inspect.getargspec
^^^^^^^^^^^^^^^^^^
AttributeError: module 'inspect' has no attribute 'getargspec'. Did you mean: 'getargs'?
by the looks of it though, I don't see any application code there
Just for a follow-up. I got it working just fine after removing python3
from linuxbrew and installing it via apt get.
One comment on my usage of it. I set it up as a startup application upon login, once you close it it closes the browser but the backend application stays running. This causes issues when it's a startup app because it's running in the background and won't open up again without a reboot. Would be nice if it detected the browser closed and automatically shutdown. Or possibly do that with a command-line option.
Just for a follow-up. I got it working just fine after removing
python3
from linuxbrew and installing it via apt get.One comment on my usage of it. I set it up as a startup application upon login, once you close it it closes the browser but the backend application stays running. This causes issues when it's a startup app because it's running in the background and won't open up again without a reboot. Would be nice if it detected the browser closed and automatically shutdown. Or possibly do that with a command-line option.
Just catching up on what an Atari VCS is. Fascinating, definitely did not anticipate folks trying to get stuff working on that. Is it performant? I notice some occasional performance hiccups on Pi 3 without overclocking.
As for your close issue, how are you closing it? By shutting down the browser? The preferred way is through the pikaraoke settings menu "Quit Pikaraoke", which will properly kill all the subprocesses. The headed process launches the browser via chromedriver (selenium) in order to auto-dismiss the interaction prompt. We can probably detect the termination of that subprocess, but not sure of a good approach for folks who are running the headed UI on another machine. There probably isn't a reliable way to detect a remote browser shutdown.
I'm mostly using the Atari VCS because I already have it ;) I'm still considering picking up a Pi for this, but wanted to make sure I have a working solution before spending the money. The VCS doesn't seem to have any performance issues, though I believe it's quite a bit more powerful than a Pi 3.
Yeah, I was just closing the browser. I'll try next time from the web app.
For headless, I would expect a different story. I would want it running all the time. I setup a docker server that's always on so I just have to open a browser to the splash URL to get the karaoke going. I don't know which option I'm going to go with so far, now that I have both working. Both require me to have a keyboard and mouse connected to the machine to start it up. (though I could maybe get around that with a dedicated pi that boots to it.)
Though I did think it would be great if the headless option was just a video stream that could be picked up by VLC. Because then I can just open the VLC app on my Apple TV and connect to the stream. I wouldn't need the Atari VCS or another Pi for this option, which could be nice. I did some experiments and could stream it from ffmpeg, very much like you're doing to the browser. But it gets tricky when you want to change the video or add overlays to it (such as who's signing next.)
Just wanted to throw an update: I am trying to use this in my ubuntu server. I noticed that for some reason, if I run it with --headless without prefer-ip, it fails to load the ffmpeg stream. However if I enable prefer-ip then it works. Is there a reason why the hostname would fail vs IP?
EDIT: i was able to get around it by passing a different url to ffmpeg. i still kept the stream URL the same but for ffmpeg i passed in this
ffmpeg_url = f"http://0.0.0.0:{self.ffmpeg_port}/{time}"
That seemed to work
@frankchau93
I'm not sure why that might be, seems to work fine for me on the various setups I've tried. I wonder if we should always use the IP as the now_playing stream url under the hood instead of trying the hostname.
Where did you specify that ffmpeg_url exactly? Not seeing where you'd do that in the code.
@vicwomg I created a new variable, ffmpeg_url that looks like the following... `logging.info(f"Playing file: {file_path} transposed {semitones} semitones") stream_url = f"{self.url_parsed.scheme}://{self.url_parsed.hostname}:{self.ffmpeg_port}/{int(time.time())}" pitch = 2**(semitones/12) #The pitch value is (2^x/12), where x represents the number of semitones
# Extract time component from stream_url
time_component = stream_url.split('/')[-1]
# Construct ffmpeg_url
ffmpeg_url = f"http://0.0.0.0:{self.ffmpeg_port}/{time_component}"`
Then I passed it to the various ffmpeg calls
output = ffmpeg.output(audio, video, ffmpeg_url, vcodec=vcodec, acodec="aac", pix_fmt="yuv420p", listen=1, f="mp4", video_bitrate=vbitrate, movflags="frag_keyframe+default_base_moof")
Although i kept stream_url to be passed in the frontend. That ended up working. I think it had something to do with the url only being accessible to the machine if I used the hostname. If I used 0.0.0.0 then I can access it from either IP or hostname. Not sure why, it might be how I setup my ubuntu server.
So far it mostly works! The only thing I noticed is, if i refresh the page or if there's something wrong, the song queue would hang and would constantly be 'paused'. There would be no way for me to skip or refresh to fix it without restarting it manually. Not sure if there's a way for me to 'reset' the queue or find a way to continue if it hangs like that.
@vicwomg So far it mostly works! The only thing I noticed is, if i refresh the page or if there's something wrong, the song queue would hang and would constantly be 'paused'. There would be no way for me to skip or refresh to fix it without restarting it manually. Not sure if there's a way for me to 'reset' the queue or find a way to continue if it hangs like that.
Thanks for that, I'll add some version of this ffmpeg_url / stream_url distinction to the merge just to cover the bases of configurations like yours. Seems to work fine.
I just merged some changes that make error recovery for page refreshes and failed streams better. There's a timeout of 10s and then it will clear that song and move on.
Getting close to merging this to main.
Merged to main
I love that this is working on a separate browser, but I need to be able to proxy this through nginx and/or cloudflare and noticed when I do this, the video no longer plays. Is this a websocket issue?
Merry Christmas btw! Love this project!
Not sure, never tried a non LAN configuration. Video plays over port 5556, make sure that’s also allowed through the firewall.
On Mon, Dec 25, 2023 at 4:55 PM HonestLai @.***> wrote:
I love that this is working on a separate browser, but I need to be able to proxy this through nginx and/or cloudflare and noticed when I do this, the video no longer plays. Is this a websocket issue?
— Reply to this email directly, view it on GitHub https://github.com/vicwomg/pikaraoke/issues/277#issuecomment-1869172901, or unsubscribe https://github.com/notifications/unsubscribe-auth/AA7KXNRX6F2PKBXXL3JQJVDYLIOANAVCNFSM6AAAAAA7TVH2E6VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTQNRZGE3TEOJQGE . You are receiving this because you modified the open/close state.Message ID: @.***>
Hmm... got it... proxy'ing doesn't rely on port forwarding, but it would make sense now that the video would not be delivered. I'm guessing it's TCP 5556.
I would very much like to remove the pygame dependency. Rendering graphics natively is nice, but the dependencies surrounding pygame are a major pain point. I think it's the main reason folks have trouble installing on different platforms. On pi alone, pulling down these libraries can take 20 minutes.
Ideally we could render the splash screen AND the video on Flask inside of an HTML page. This would be universally renderable on all windowed systems.
In addition, maybe we can remove vlc while we're at it. It's pretty bloated for what this is doing. We can use ffmpeg to stream the video to a URL, including transposing in real-time
ffmpeg -i <inputfile> -filter:a "rubberband=pitch=0.5" -listen 1 -f mp4 -movflags frag_keyframe+empty_moov http://localhost:8080/
Pitch value calculation: (2^x/12), where x represents the number of semitones you would like to transpose
The splash screen has a hidden video tag which launches the video when it is queued up.
Pros:
Cons:
Questions: