rhasspy / piper

A fast, local neural text to speech system
https://rhasspy.github.io/piper-samples/
MIT License
5.77k stars 417 forks source link

Unable to run prebuilt binary on M1 Mac #321

Open ErikLundin98 opened 8 months ago

ErikLundin98 commented 8 months ago

Hi! When simply downloading and extracting the prebuilt binary found here, I get the following error when running:


> echo "Hej, det är Erik" | \                                   
  ~/Prog/hobby/lundin_bot/lundin_bot/bin/piper/piper --model ~/Prog/hobby/lundin_bot/lundin_bot/bin/sv_SE-nst-medium.onnx --output_file test.wav

dyld[29280]: Library not loaded: @rpath/libespeak-ng.1.dylib
  Referenced from: <65D01FDC-B71E-3786-8B0D-0BFEEC801633> /Users/lundinerik/Prog/hobby/lundin_bot/lundin_bot/bin/piper/piper
  Reason: tried: '/usr/local/lib/libespeak-ng.1.dylib' (no such file), '/usr/lib/libespeak-ng.1.dylib' (no such file, not in dyld cache)
[1]    29279 done       echo "Hej, det är Erik" | 
       29280 abort      ~/Prog/hobby/lundin_bot/lundin_bot/bin/piper/piper --model  --output_file 

I suspect that I need to install something to get the dylib file, but I do not know what. Any ideas on how to fix this and make piper run correctly?

ErikLundin98 commented 8 months ago

For anyone running into the same issue, what was missing was some .dylib files for libespeak, oonxruntime and piper_phonemize. All of these files are available as a release for piper-phonemize

Here are steps that I used to fix it.

softwareupdate --install-rosetta

wget https://github.com/rhasspy/piper-phonemize/releases/download/2023.11.14-4/piper-phonemize_macos_x64.tar.gz -O piper-phonemize.tar.gz

tar -xvzf piper-phonemize.tar.gz 

install_name_tool -change @rpath/libespeak-ng.1.dylib absolute_path_to_piper_phonemize_download_dir/piper-phonemize/lib/libespeak-ng.1.dylib absolute_path_to_piper_binaries_dir/piper

install_name_tool -change @rpath/libonnxruntime.1.14.1.dylib absolute_path_to_piper_phonemize_download_dir/piper-phonemize/lib/libonnxruntime.1.14.1.dylib absolute_path_to_piper_binaries_dir/piper

install_name_tool -change @rpath/libpiper_phonemize.1.dylib absolute_path_to_piper_phonemize_download_dir/piper-phonemize/lib/libpiper_phonemize.1.dylib absolute_path_to_piper_binaries_dir/piper

After doing these steps, I was able to successfully run the piper binary.

You can verify that the linkings are succesfully applied by using

otool -l absolute_path_to_piper_binaries_dir/piper

Keeping this open still, as I think it's worth discussing if there's a more straightforward approach to get it to work. Perhaps a start could be to include these dylib files in the released binaries

Thanks :)

FotieMConstant commented 7 months ago

Hey man, how did you get it working on M1? having issues here even install...

KarlLivesey commented 7 months ago

it would be great to either update the instalation documentation or to have the dylibs packaged this just isn't something many will get or beable to install worst case give two builds 1 dynamic and 1 static linked

kashacv commented 4 months ago

@ErikLundin98 6 months later, your solution still works. I tried it on MB Pro M1. You saved me a lot of headache. 🙏

tgrushka commented 1 month ago

You don't (or at least no longer?) need Rosetta, because the macOS arm64 piper-phonemize release (now?) includes the needed binaries.

The above was a bit painful for me so I wrote a script to make this easier for someone in the future.

( Also, you can use sox in place of aplay on macOS (because, of course, afplay doesn't work) to play piper output live, but the command is a bit different:

First, install it via Homebrew with brew install sox

piper ... --output-raw | sox -t raw -r 22050 -b 16 -e signed -c 1 - -d )

The following bash script does the following: CAUTION! This requires sudo if installing to /usr/local -- remove sudo commands if installing to a user directory (I haven't tested this)

  1. Downloads piper and piper-phonemize into a temp directory;
  2. Extracts binaries to user location;
  3. Downloads specified model into temp directory;
  4. Copies specified model into piper installed directory;
  5. Remaps linked libraries in piper binary to the binary locations in piper-phonemize installed directory;
  6. Tests to see if piper works, and if so, deletes the temp download files.
#!/bin/bash

# Optionally install sox to play live with:
# brew install sox

# Replace with the temporary directory you want to download into
export DOWNLOAD_DIR=$TMPDIR/piper

# Replace with the directories in which you want to install piper and piper-phonemize
export PIPER_DIR=/usr/local/piper
export PIPER_PHONEMIZE_DIR=/usr/local/piper-phonemize

# Replace with current release versions
export PIPER_RELEASE=2023.11.14-2
export PIPER_PHONEMIZE_RELEASE=2023.11.14-4

# Select a model from https://github.com/rhasspy/piper/blob/master/VOICES.md
# We separate the language, locale, and name because the URLs are complicated
export MODEL_LANG=en
export MODEL_LOCALE=US
export MODEL_NAME=lessac
export MODEL_QUALITY=high

# Set your own test text to speak
export TEST_TEXT="Let's see if we can get piper working on macOS. Cool! We don't need the x86 build and Rosetta on M1 any more! We can just download the arm64 versions and repoint the rpaths using install_name_tool."

############################################################
# Less likely need to change things below this line
# (except, can likely remove sudo if installing inside $HOME)

export MODEL_LANG_AND_LOC="$MODEL_LANG""_$MODEL_LOCALE"
export MODEL_ID="$MODEL_LANG_AND_LOC-$MODEL_NAME-$MODEL_QUALITY"

# Create temporary directory in which to download files
mkdir -p $DOWNLOAD_DIR
cd $DOWNLOAD_DIR

# Download piper
echo "Downloading piper..."
curl -L -o piper_macos_aarch64.tar.gz "https://github.com/rhasspy/piper/releases/download/$PIPER_RELEASE/piper_macos_aarch64.tar.gz"

# Download piper-phonemize
echo "Downloading piper-phonemize..."
curl -L -o piper-phonemize_macos_aarch64.tar.gz "https://github.com/rhasspy/piper-phonemize/releases/download/$PIPER_PHONEMIZE_RELEASE/piper-phonemize_macos_aarch64.tar.gz"

# Download model and model config file:
echo "Downloading model: $MODEL_ID..."
curl -L -o "$MODEL_ID.onnx" "https://huggingface.co/rhasspy/piper-voices/resolve/v1.0.0/$MODEL_LANG/$MODEL_LANG_AND_LOC/$MODEL_NAME/$MODEL_QUALITY/$MODEL_ID.onnx?download=true"
curl -L -o "$MODEL_ID.onnx.json" "https://huggingface.co/rhasspy/piper-voices/resolve/v1.0.0/$MODEL_LANG/$MODEL_LANG_AND_LOC/$MODEL_NAME/$MODEL_QUALITY/$MODEL_ID.onnx.json?download=true"

# Extract piper into `PIPER_DIR`, without adding an extra `piper` subdirectory under `PIPER_DIR`.
sudo mkdir -p $PIPER_DIR
sudo tar --strip-components=1 --directory $PIPER_DIR -xzf piper_macos_aarch64.tar.gz

# Extract piper-phonemize into `PIPER_PHONEMIZE_DIR`, without adding an extra `piper-phonemize` subdirectory under `PIPER_PHONEMIZE_DIR`.
sudo mkdir -p $PIPER_PHONEMIZE_DIR
sudo tar --strip-components=1 --directory $PIPER_PHONEMIZE_DIR -xzf piper-phonemize_macos_aarch64.tar.gz

# Copy model and model config files into piper directory
sudo cp "$MODEL_ID.onnx" $PIPER_DIR/
sudo cp "$MODEL_ID.onnx.json" $PIPER_DIR/

# Get the libonnxruntime version for the installed release dynamically using `otool`.
export LIBONNXRUNTIME_VERSION=$(otool -l $PIPER_DIR/piper | sed -n 's/.*libonnxruntime\.\([0-9]\{1,\}\.[0-9]\{1,\}\.[0-9]\{1,\}\).*/\1/p')

# install_name_tool: change dynamic shared library install names
# This tool changes the rpaths in the piper binary to point to new locations for these libraries
sudo install_name_tool -change @rpath/libespeak-ng.1.dylib $PIPER_PHONEMIZE_DIR/lib/libespeak-ng.1.dylib $PIPER_DIR/piper
sudo install_name_tool -change @rpath/libonnxruntime.$LIBONNXRUNTIME_VERSION.dylib $PIPER_PHONEMIZE_DIR/lib/libonnxruntime.$LIBONNXRUNTIME_VERSION.dylib $PIPER_DIR/piper
sudo install_name_tool -change @rpath/libpiper_phonemize.1.dylib $PIPER_PHONEMIZE_DIR/lib/libpiper_phonemize.1.dylib $PIPER_DIR/piper

# Test, and if succeeds, remove temp download files/(empty) temp folder.
# (won't work in fish shell)
( \
    command -v sox &&
    ( \
        echo "$TEST_TEXT" \
            | $PIPER_DIR/piper --model $PIPER_DIR/$MODEL_ID.onnx --output-raw \
            | sox -t raw -r 22050 -b 16 -e signed -c 1 - -d \
    ) || ( \
        echo "$TEST_TEXT" \
            | $PIPER_DIR/piper --model $PIPER_DIR/$MODEL_ID.onnx --output_file $DOWNLOAD_DIR/test.wav \
    ) && afplay $DOWNLOAD_DIR/test.wav \
) \
&& rm $DOWNLOAD_DIR/{*.onnx,*.onnx.json,test.wav,piper_macos_aarch64.tar.gz,piper-phonemize_macos_aarch64.tar.gz} \
&& rmdir $DOWNLOAD_DIR
PeterHagen commented 1 month ago

You don't (or at least no longer?) need Rosetta, because the macOS arm64 piper-phonemize release (now?) includes the needed binaries.

Great! This works! Can I opt for adding this information somewhere in the available downloads? Or maybe change the build so these libraries are added?