Skip to content

Commit

Permalink
Merge pull request #375 from vicwomg/342-volume-normalization
Browse files Browse the repository at this point in the history
342 volume normalization
  • Loading branch information
vicwomg authored Sep 2, 2024
2 parents 16c22c2 + 4c375e6 commit 089cf5a
Show file tree
Hide file tree
Showing 9 changed files with 423 additions and 109 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
*.swp
.venv/
.venv*
/.vscode/
__pycache__/
dist/
songs/
Expand Down
8 changes: 7 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
{
"pylint.args": ["--rcfile=${workspaceFolder}/code_quality/.pylintrc"],
"pylint.args": [
"--rcfile=${workspaceFolder}/code_quality/.pylintrc",
"--max-line-length=100"
],
"[python]": {
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.organizeImports": "explicit"
}
},
"[yaml]": {
"editor.formatOnSave": false
},
"isort.args": ["--profile", "black"]
}
15 changes: 15 additions & 0 deletions code_quality/.vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Suggested vscode settings

{
"pylint.args": ["--rcfile=${workspaceFolder}/code_quality/.pylintrc"],
"[python]": {
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.organizeImports": "explicit"
}
},
"[yaml]": {
"editor.formatOnSave": false
},
"isort.args": ["--profile", "black"]
}
29 changes: 24 additions & 5 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,15 @@ sudo apt-get install chromium-chromedriver -y

### Install pikaraoke

Optional: create a virtual environment. This is recommended to prevent conflicts with other global python packages.
#### Create a virtual environment (optional)

On the other hand, if you install globally without venv, you can launch pikaraoke without activating a venv each time, which is more convenient and fine for many users. The choice is yours.
Using a virtual environment (venv) is recommended to prevent conflicts with other global python packages.

See [the python documentation](https://docs.python.org/3/library/venv.html) for more details on venv.
You may find it more convenient to skip these steps, which allows you to launch pikaraoke without activating a venv first, but you run the risk of package conflicts.

If you don't install a lot of python projects with pip, that skipping venv is probably be fine. The choice is yours. See [the python documentation](https://docs.python.org/3/library/venv.html) for more details on venv.

Raspberry Pi/Linux/OSX:

```sh
# Create a .venv directory in the homedir
Expand All @@ -76,7 +80,20 @@ python -m venv ~/.venv
source ~/.venv/bin/activate
```

Install pikaraoke from PyPi on the host into your venv:
Windows (Powershell terminal):

```batch
:: Create a venv in Windows in your homedir
cd $HOME
python -m venv .venv
.venv\Scripts\activate
```

You should see a "(venv)" prefix in your terminal prompt if the venv is successfully activated.

#### Install pikaraoke via pip

Next, install pikaraoke from PyPi on the host into your venv:

```sh
# Install pikaraoke from PyPi
Expand All @@ -94,8 +111,10 @@ Pikaraoke is now installed in the `$PATH` with the command line interface `pikar
pikaraoke
```

This will start pikaraoke in headed mode, and open Chrome browser with the splash screen. You can then connect to the QR code via your mobile device and start downloading and queueing songs.

Virtual env users: note that if you close your terminal between launches, you'll need to run:
`source ~/.venv/bin/activate` before launching pikaraoke again.
`source ~/.venv/bin/activate` or `.venv\Scripts\activate` (windows) before launching pikaraoke again.

### More Options

Expand Down
86 changes: 79 additions & 7 deletions docs/TROUBLESHOOTING.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,67 @@
## Troubleshooting

Note that much of this info is relevant only to Raspberry Pi devices.

### How do I update pikaraoke to the latest version?

`pip install --upgrade pikaraoke`

### How do I display all the command line options?

`pikaraoke --help`

Here is a snapshot (may not be up to date):

```
usage: pikaraoke [-h] [-p PORT] [--window-size WINDOW_SIZE] [-f FFMPEG_PORT] [-d DOWNLOAD_PATH [DOWNLOAD_PATH ...]]
[-y YOUTUBEDL_PATH [YOUTUBEDL_PATH ...]] [-v VOLUME] [-n] [-s SPLASH_DELAY] [-t SCREENSAVER_TIMEOUT] [-l LOG_LEVEL]
[--hide-url] [--prefer-hostname] [--hide-raspiwifi-instructions] [--hide-splash-screen] [--high-quality]
[--logo-path LOGO_PATH [LOGO_PATH ...]] [-u URL] [-m FFMPEG_URL] [--hide-overlay] [--admin-password ADMIN_PASSWORD]
options:
-h, --help show this help message and exit
-p PORT, --port PORT Desired http port (default: 5555)
--window-size WINDOW_SIZE
Desired window geometry in pixels, specified as width,height
-f FFMPEG_PORT, --ffmpeg-port FFMPEG_PORT
Desired ffmpeg port. This is where video stream URLs will be pointed (default: 5556)
-d DOWNLOAD_PATH [DOWNLOAD_PATH ...], --download-path DOWNLOAD_PATH [DOWNLOAD_PATH ...]
Desired path for downloaded songs. (default: ~/pikaraoke-songs)
-y YOUTUBEDL_PATH [YOUTUBEDL_PATH ...], --youtubedl-path YOUTUBEDL_PATH [YOUTUBEDL_PATH ...]
Path of youtube-dl. (default: yt-dlp)
-v VOLUME, --volume VOLUME
Set initial player volume. A value between 0 and 1. (default: 0.85)
-n, --normalize-audio
Normalize volume. May cause performance issues on slower devices (default: False)
-s SPLASH_DELAY, --splash-delay SPLASH_DELAY
Delay during splash screen between songs (in secs). (default: 3 )
-t SCREENSAVER_TIMEOUT, --screensaver-timeout SCREENSAVER_TIMEOUT
Delay before the screensaver begins (in secs). (default: 300 )
-l LOG_LEVEL, --log-level LOG_LEVEL
Logging level int value (DEBUG: 10, INFO: 20, WARNING: 30, ERROR: 40, CRITICAL: 50). (default: 20 )
--hide-url Hide URL and QR code from the splash screen.
--prefer-hostname Use the local hostname instead of the IP as the connection URL. Use at your discretion: mDNS is not guaranteed
to work on all LAN configurations. Defaults to False
--hide-raspiwifi-instructions
Hide RaspiWiFi setup instructions from the splash screen.
--hide-splash-screen, --headless
Headless mode. Don't launch the splash screen/player on the pikaraoke server
--high-quality Download higher quality video. Note: requires ffmpeg and may cause CPU, download speed, and other performance
issues
--logo-path LOGO_PATH [LOGO_PATH ...]
Path to a custom logo image file for the splash screen. Recommended dimensions ~ 2048x1024px
-u URL, --url URL Override the displayed IP address with a supplied URL. This argument should include port, if necessary
-m FFMPEG_URL, --ffmpeg-url FFMPEG_URL
Override the ffmpeg address with a supplied URL.
--hide-overlay Hide overlay that shows on top of video with pikaraoke QR code and IP
--admin-password ADMIN_PASSWORD
Administrator password, for locking down certain features of the web UI such as queue editing, player controls,
song editing, and system shutdown. If unspecified, everyone is an admin.
```

### I'm not hearing audio out of the headphone jack (rpi)

See: https://www.raspberrypi.com/documentation/computers/configuration.html#change-audio-output
You should be able to right-click the speaker icon in the upper right of the desktop of the OS to change the audio output device. If that fails, see the official raspberry pi docs on [changing audio output](https://www.raspberrypi.com/documentation/computers/configuration.html#change-audio-output)

### How to auto-start PiKaraoke (rpi)

Expand All @@ -17,13 +72,22 @@ mkdir /home/pi/.config/autostart
nano /home/pi/.config/autostart/pikaraoke.desktop
```

Add this to the file, assuming you installed to /home/pi/pikaraoke, change the Exec path accordingly if not
If you installed pikaraoke globally with pip, this should work:

```
[Desktop Entry]
Type=Application
Name=Pikaraoke
Exec=pikaraoke
```

If you installed to a .venv, then you may need to adjust the exec path to the full path of the executable

```
[Desktop Entry]
Type=Application
Name=Pikaraoke
Exec=/home/pi/pikaraoke/scripts/pikaraoke.sh
Exec=/home/pi/.venv/bin/pikaraoke
```

Restart and it should auto-launch on your next boot.
Expand All @@ -34,14 +98,16 @@ Note that if your wifi/network is inactive pikaraoke will error out 10 seconds a

### How to keep the screen from turning off when idle (rpi)

Disable "screen blanking" in raspi-config: https://www.raspberrypi.com/documentation/computers/configuration.html#display-options
Disable "screen blanking" in `raspi-config`. See this [article](https://www.raspberrypi.com/documentation/computers/configuration.html#display-options)

### Songs aren't downloading!

Make sure youtube-dl is up to date, old versions have higher failure rates due to security changes in Youtube. You can see your current version installed by navigating to `Info > System Info > Youtube-dl version`. The version number is usually the date it was released. If this is older than a couple of months, chances are it will need an update.

You can update youtube-dl directly from the web UI. Go to `Info > Update Youtube-dl`

You can also just restart pikaraoke, it checks for updates on every launch.

### Downloads are slow!

youtube-dl is very CPU intensive, especially for single-core devices like the pi models zero and less-than 2. The more simultaneous downloads there are, the longer they will take. Try to limit it to 1-2 at a time. Pi 3 can handle quite a bit more.
Expand Down Expand Up @@ -72,9 +138,9 @@ Finally, this package can set up your pi as a self-configuring wireless access p

Yes, but you can only access your existing library and won't be able to download new songs.

If you run your pi as a wifi access point, your browser can connect to that access point, and it should work. See: https://www.raspberrypi.org/documentation/configuration/wireless/access-point.md
If you run your pi as a wifi access point, your browser can connect to that access point, and it should work. See this [article](https://www.raspberrypi.org/documentation/configuration/wireless/access-point.md).

You can also try this: https://github.com/jasbur/RaspiWiFi (used for configuring wifi connections headless). While it's in AP mode, you can connect to the pi as an AP and connect directly to it at http://10.0.0.1:5555
You can also try [RaspiWiFi](https://github.com/jasbur/RaspiWiFi) (used for configuring wifi connections headless). While it's in AP mode, you can connect to the pi as an AP and connect directly to it at http://10.0.0.1:5555

### Where do I plug in a microphone?

Expand All @@ -86,6 +152,12 @@ Ideally, you'd have a mixer and amplifier that you could run the line out of the

While a song is playing, the home screen of the web interface will show a transpose slider. Slide it up or down based on your preference and press the "ok" button to restart the song in the given key.

### Some downloads have higher/lower volume than the rest. How can I normalize the audio?

You can try the normalize command line option `pikaraoke --normalize-audio`.

Note that this is rather CPU intensive and might struggle on slower pi devices.

### How do I add cdg or mp3+cdg zip files?

You'll need to add them manually by copying them to the root of your download folder. Run `pikaraoke --help` and look under DOWNLOAD_PATH to find out what the default folder is, or specify your own. Only cdg/mp3 pairs and .zip files are supported.
Expand All @@ -104,4 +176,4 @@ You can alternately run headless if you launch the splash screen manually on a s

The splash confirmation screen is an unfortunate necessity due to modern browser permissions disabling video autoplay. A single interaction will enable it, and the confirmation screen serves as this interaction. Hopefully your TV has a way to click the button on the screen with the remote or otherwise.

If you want to try without confirmation, you can add a parameter to the end of the splash screen URL "confirm=false". Ex: `http://pikaraoke.local:5555/splash.html?confirm=false` but there's no guarantee that videos will play; it depends on the embedded browser implementation.
If you want to try without confirmation, you can add a parameter to the end of the splash screen URL "confirm=false". Ex: `http://pikaraoke.local:5555/splash?confirm=false` but there's no guarantee that videos will play; it depends on the embedded browser implementation.
11 changes: 11 additions & 0 deletions pikaraoke/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -708,6 +708,7 @@ def main():
default_port = 5555
default_ffmpeg_port = 5556
default_volume = 0.85
default_normalize_audio = False
default_splash_delay = 3
default_screensaver_delay = 300
default_log_level = logging.INFO
Expand Down Expand Up @@ -762,6 +763,15 @@ def main():
default=default_volume,
required=False,
)
parser.add_argument(
"-n",
"--normalize-audio",
help="Normalize volume. May cause performance issues on slower devices (default: %s)"
% default_normalize_audio,
action="store_true",
default=default_normalize_audio,
required=False,
)
parser.add_argument(
"-s",
"--splash-delay",
Expand Down Expand Up @@ -885,6 +895,7 @@ def main():
splash_delay=args.splash_delay,
log_level=args.log_level,
volume=parsed_volume,
normalize_audio=args.normalize_audio,
hide_url=args.hide_url,
hide_raspiwifi_instructions=args.hide_raspiwifi_instructions,
hide_splash_screen=args.hide_splash_screen,
Expand Down
11 changes: 9 additions & 2 deletions pikaraoke/karaoke.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ class Karaoke:
ffmpeg_log = None
ffmpeg_version = get_ffmpeg_version()
supports_hardware_h264_encoding = supports_hardware_h264_encoding()
normalize_audio = False

raspberry_pi = is_raspberry_pi()
os_version = get_os_version()
Expand All @@ -81,6 +82,7 @@ def __init__(
hide_splash_screen=False,
high_quality=False,
volume=0.85,
normalize_audio=False,
log_level=logging.DEBUG,
splash_delay=2,
youtubedl_path="/usr/local/bin/yt-dlp",
Expand All @@ -101,6 +103,7 @@ def __init__(
self.high_quality = high_quality
self.splash_delay = int(splash_delay)
self.volume = volume
self.normalize_audio = normalize_audio
self.youtubedl_path = youtubedl_path
self.logo_path = self.default_logo_path if logo_path == None else logo_path
self.hide_overlay = hide_overlay
Expand Down Expand Up @@ -132,6 +135,7 @@ def __init__(
high quality video: {self.high_quality}
download path: {self.download_path}
default volume: {self.volume}
normalize audio: {self.normalize_audio}
youtube-dl path: {self.youtubedl_path}
logo path: {self.logo_path}
log_level: {log_level}
Expand Down Expand Up @@ -419,11 +423,14 @@ def play_file(self, file_path, semitones=0):
)
vbitrate = "5M" # seems to yield best results w/ h264_v4l2m2m on pi, recommended for 720p.

# copy the audio stream if no transposition, otherwise use the aac codec
# copy the audio stream if no transposition/normalization, otherwise reincode with the aac codec
is_transposed = semitones != 0
acodec = "aac" if is_transposed else "copy"
acodec = "aac" if is_transposed or self.normalize_audio else "copy"
input = ffmpeg.input(fr.file_path)
audio = input.audio.filter("rubberband", pitch=pitch) if is_transposed else input.audio
# normalize the audio
audio = audio.filter("loudnorm", i=-16, tp=-1.5, lra=11) if self.normalize_audio else audio

# Ffmpeg outputs "Stream #0" when the stream is ready to consume
stream_ready_string = "Stream #"

Expand Down
Loading

0 comments on commit 089cf5a

Please sign in to comment.