rhasspy / piper-phonemize

C++ library for converting text to phonemes for Piper
MIT License
86 stars 73 forks source link

Building for MacOS and iOS #14

Open jaocode opened 1 year ago

jaocode commented 1 year ago

I'm looking for instructions on how to build this for use with Python on MacOS. The piper-tts pip package exists for MacOS, but this dependency does not. I assume it is possible because there is a MacOS build of the library.

I'd also like to build this for use with iOS. Has this been attempted?

nickolay commented 11 months ago

I was curious about it too and saw https://github.com/rhasspy/piper-phonemize/pull/13, which motivated me to try and get it running. The following worked on my machine (Intel, Ventura, macports):

  1. The C++ build worked with no modification (assuming you have the common build prerequisites, such as XCode tools and cmake):
    $ git clone git@github.com:rhasspy/piper-phonemize.git pp
    $ cd pp
    $ git checkout fccd4f335aa68ac0b72600822f34d84363daa2bf -b my   # (tag: 2023.11.14-4, Date:   Tue Nov 14 11:54:34 2023 -0600)
    $ make
  2. To get the test binary working I had to override the default library and --espeak-data paths, as by default it was looking only in global folders (e.g. /usr)
    $ export DYLD_LIBRARY_PATH=`pwd`/install/lib/   # otherwise I got: dyld[82606]: Library not loaded: @rpath/libpiper_phonemize.1.dylib
    $ echo "testing one two three" | ./install/bin/piper_phonemize -l en-us --espeak-data ./install/share/espeak-ng-data/
  3. To build the python package, I needed to tweak the path to the C++ headers and libraries from step 1 again (I see that similar changes were needed for a Windows build), and also to change __version__ to the one piper-tts expects:
    $ python -m venv venv
    $ source venv/bin/activate
    $ pip install -U pip
    $ patch -p1 <<EOF
    --- a/setup.py
    +++ b/setup.py
    @@ -9 +9 @@ _DIR = Path(__file__).parent
    -_ESPEAK_DIR = _DIR / "espeak-ng" / "build"
    +_ESPEAK_DIR = _DIR / "install"
    @@ -13 +13 @@ _ONNXRUNTIME_DIR = _LIB_DIR / "onnxruntime"
    -__version__ = "1.2.0"
    +__version__ = "1.1.0"
    EOF
    $ pip install .
    $ cp -rp ./install/share/espeak-ng-data venv/lib/python3.10/site-packages/piper_phonemize/espeak-ng-data   # Otherwise I got Error processing file '/usr/share/espeak-ng-data/phontab': No such file or directory.
  4. Afterwards I was able to install and use piper-tts:
    $ pip install piper-tts
    $ echo 'Welcome to the world of speech synthesis!' |   venv/bin/piper --model en_US-lessac-medium --output_file welcome.wav
    $ afplay welcome.wav
williamcorney commented 11 months ago

Thanks @nickolay for posting that you got it working and the steps you had to take

I had prior to your post made further attempts but given up.

Can you clarify a few points ?

1.The test binary mentioned in second step is the one you built in first step I presume and which resides in the folder you did the build eg downloads.

2.are the exports commands in step 2 exactly what I would need to run , or is there any alteration I need to make depending where I built the piper-phonemize

  1. Iā€™m not really clear what location pwd/install/lib/ā€˜ refers to. It sounds like this is the equivalent of a command like ./foldername which appends the path of parent folder to make a complete path ?
  2. are the commands in step 3 to build the python modules exactly what anyone needs to copy paste to get this working? Do you have to be in a particular location or folder when you run ?

Thankyou

nickolay commented 11 months ago

Hey @williamcorney, I tested this specific sequence of commands from scratch before posting, but I can't guarantee it will work for everyone. (In addition to than what I have already mentioned, I was using bash and Python 3.10 for this.)

Re your first point: I cloned this repository to a local folder named pp in (1.1); all the other paths are relative to this directory. Both ./ and `pwd`/ refer to the current directory (so pp in my guide), so the location of the root (pp) folder shouldn't matter.

Yes, the ./install folder was created after I ran make. It has a bin subfolder, containing the test binary, also include, lib, and share.

Re your 2nd and 3rd questions: you should be able to re-use the commands with no modifications. You're right about the meaning of `pwd`/ ā€” I used the absolute path for DYLD_LIBRARY_PATH to be able to invoke piper-tts after having changed the current directory. You will see that it resolves to the install/lib subdirectory of the git working directory, e.g.:

$ echo $DYLD_LIBRARY_PATH
/Users/nickolay/pp/install/lib/

Re 4th question: the step 3 continues the commands from steps 1 and 2, so is executed inside the same git checkout (named pp in my example).

If you have trouble with the multiline-heredoc patch -p0 <<EOF, you can instead edit setup.py by hand. The last command might need updating if the location of site-packages in your python virtual environment created via python -m venv venv is different. I'm just putting the espeak data to the folder that piper-phonemize expects.

williamcorney commented 11 months ago

Thankyou @nickolay :)

Great work

I have been able to get through all the steps and replicate your success.

Notes from my own experience

  1. I had to run 'git clone https://github.com/rhasspy/piper-phonemize.git pp' instead
  2. I had in my case to modify the line with python 3.10 to 3.11
  3. I had already prior to attempting your steps installed piper-tts by overriding dependencies and it was necessary for me to remove piper-tts then rebuild/reinstall after run the patches to setup.py.

I wasn't familiar with the patch function you used to patch the setup.py file so confused at first. Handy little feature thanks for introducing me to that.

jaocode commented 11 months ago

Thank you @nickolay and @williamcorney. Following your responses I was able to build and install it on my M1 MacBook.

phillipeloher commented 9 months ago

Thank you @nickolay , your steps worked perfectly.

williamcorney commented 8 months ago

another step I found to be necessary after reinstalling recently

Error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1000)>

Cause It seems that, for some reason, Brew has not run the Install Certificates.command that comes in the Python3 bundle for Mac.

Solution

The solution to this issue is to run the following script (copied from Install Certificates.command) after brew install python3. I havent pasted here to not spam this post but you can see the full post here.

https://stackoverflow.com/questions/44649449/brew-installation-of-python-3-6-1-ssl-certificate-verify-failed-certificate/44649450#44649450

williamcorney commented 7 months ago

I have created wheels for python 3.10 and 3.12 which makes this work much smoother now :)

It was a sharp learning curve to understand what needed to be done as barely understood what a wheel was before let alone how to make one lol

download and extract the whl file and install by running the command

pip3 install -f /REPLACE/WITH/PATH/WHERE/YOU/DOWNLOADED/WHEEL/FILE piper-phonemize

piper_phonemize-1.1.0-cp310-cp310-macosx_13_0_x86_64.whl.zip piper_phonemize-1.1.0-cp311-cp311-macosx_13_0_x86_64.whl.zip piper_phonemize-1.1.0-cp312-cp312-macosx_13_0_x86_64.whl.zip piper_phonemize-1.1.0-cp311-cp311-macosx_10_14_x86_64.whl.zip piper_phonemize-1.1.0-cp312-cp312-macosx_10_14_universal2.whl.zip

These of course are intended for Intel based Mac.

image

williamcorney commented 7 months ago

@synesthesiam

Can these wheels be added to pypi for macos ? I haven't done before so not sure the process

Thank you

synesthesiam commented 7 months ago

I've uploaded the wheels above to PyPI :+1:

brainiakk commented 6 months ago

Thanks alot @nickolay & @williamcorney šŸ’†šŸ¼ā€ā™‚ļø my head aches from trying to install this for weeks, but this fixed it. I don't know why espeak-ng is not available for mac or on brew and I honestly don't understand why some great py libraries installation process on mac is just horrific, it's like mac is an afterthought for some devs šŸ˜‚

bluevisor commented 6 months ago

Can someone point me to the right direction of how to make this work on an ARM Mac please?

williamcorney commented 6 months ago

Building piper-phonemize from source

  1. Open a terminal window

  2. Install Xcode command line tools xcode-select --install

  3. Install homebrew /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

  4. Install cmake with homebrew brew install cmake

  5. Run these commands
    git clone https://github.com/rhasspy/piper-phonemize.git pp cd pp git checkout fccd4f335aa68ac0b72600822f34d84363daa2bf -b my make

  6. Run export command to include location in DYLD_LIBRARY_PATH export DYLD_LIBRARY_PATH=`pwd`/install/lib/

  7. Test piper-phonemize echo "testing one two three" | ./install/bin/piper_phonemize -l en-us --espeak-data ./install/share/espeak-ng-data/

  8. Create a new python virtual environment python -m venv venv

  9. Activate environment source venv/bin/activate

  10. Use the following command to patch the setup.py with necessary changes patch -p1 <<EOF --- a/setup.py +++ b/setup.py @@ -9 +9 @@ _DIR = Path(__file__).parent -_ESPEAK_DIR = _DIR / "espeak-ng" / "build" +_ESPEAK_DIR = _DIR / "install" @@ -13 +13 @@ _ONNXRUNTIME_DIR = _LIB_DIR / "onnxruntime" -__version__ = "1.2.0" +__version__ = "1.1.0" EOF If any issue with the above long command, there is a copy earlier in thread which I know works.

  11. Install package locally pip install .

  12. Copy espeak-ng data to necessary folder ( amend if you have different python version) cp -rp ./install/share/espeak-ng-data venv/lib/python3.12/site-packages/piper_phonemize/espeak-ng-data

  13. Install piper-tts pip install piper-tts

  14. Test piper-tts echo 'Welcome to the world of speech synthesis!' | venv/bin/piper --model en_US-lessac-medium --output_file welcome.wav

Creating a wheel

These are optional but recommended steps.
If you dont then you will have to run step (2) above each and every time you open a terminal AND always give the absolute path to piper when you call it. I also found that I couldn't use the module properly in pycharm until I had installed it from my newly created wheel. Note the wheel is linked to the version of python and the architecture. You may find you need to create a separate wheel for pycharm as it may use a different version of python interpreter than terminal is using If you create the wheel you can then uninstall piper-phonemize and reinstall from the wheel You could share the wheel here for anyone else. There is a command you can run to make a more universal wheel.
I'll leave that as homework :)

  1. Install necessary packages pip install wheel setuptools pybind11 delocate
  2. Create wheel python3 setup.py bdist_wheel
  3. List dependencies of piper-phonemize.
    delocate-listdeps /example/location/of/wheel/file
    e.g. /Users/myname/pp/dist/piper_phonemize-1.1.0-cp312-cp312-macosx_10_14_universal2.whl
  4. Update wheel with the dependencies. Size of wheel will grow accordingly delocate-listdeps /example/location/of/wheel/file
bluevisor commented 6 months ago

Building piper-phonemize from source

  1. Open a terminal window
  2. Install Xcode command line tools xcode-select --install
  3. Install homebrew /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
  4. Install cmake with homebrew brew install cmake
  5. Run these commands git clone https://github.com/rhasspy/piper-phonemize.git pp cd pp git checkout fccd4f335aa68ac0b72600822f34d84363daa2bf -b my make
  6. Run export command to include location in DYLD_LIBRARY_PATH export DYLD_LIBRARY_PATH=`pwd`/install/lib/
  7. Test piper-phonemize echo "testing one two three" | ./install/bin/piper_phonemize -l en-us --espeak-data ./install/share/espeak-ng-data/
  8. Create a new python virtual environment python -m venv venv
  9. Activate environment source venv/bin/activate
  10. Use the following command to patch the setup.py with necessary changes patch -p1 <<EOF --- a/setup.py +++ b/setup.py @@ -9 +9 @@ _DIR = Path(__file__).parent -_ESPEAK_DIR = _DIR / "espeak-ng" / "build" +_ESPEAK_DIR = _DIR / "install" @@ -13 +13 @@ _ONNXRUNTIME_DIR = _LIB_DIR / "onnxruntime" -__version__ = "1.2.0" +__version__ = "1.1.0" EOF If any issue with the above long command, there is a copy earlier in thread which I know works.
  11. Install package locally pip install .
  12. Copy espeak-ng data to necessary folder ( amend if you have different python version) cp -rp ./install/share/espeak-ng-data venv/lib/python3.12/site-packages/piper_phonemize/espeak-ng-data
  13. Install piper-tts pip install piper-tts
  14. Test piper-tts echo 'Welcome to the world of speech synthesis!' | venv/bin/piper --model en_US-lessac-medium --output_file welcome.wav

Creating a wheel

These are optional but recommended steps. If you dont then you will have to run step (2) above each and every time you open a terminal AND always give the absolute path to piper when you call it. I also found that I couldn't use the module properly in pycharm until I had installed it from my newly created wheel. Note the wheel is linked to the version of python and the architecture. You may find you need to create a separate wheel for pycharm as it may use a different version of python interpreter than terminal is using If you create the wheel you can then uninstall piper-phonemize and reinstall from the wheel You could share the wheel here for anyone else. There is a command you can run to make a more universal wheel. I'll leave that as homework :)

  1. Install necessary packages pip install wheel setuptools pybind11 delocate
  2. Create wheel python3 setup.py bdist_wheel
  3. List dependencies of piper-phonemize. delocate-listdeps /example/location/of/wheel/file e.g. /Users/myname/pp/dist/piper_phonemize-1.1.0-cp312-cp312-macosx_10_14_universal2.whl
  4. Update wheel with the dependencies. Size of wheel will grow accordingly delocate-listdeps /example/location/of/wheel/file

Thank you so much for the detailed instruction, I finally got it working!

A few things to note hope it helps others: 1, Above instruction assumes bash or zsh shell, if you are using fish shell like me, switch to bash first. 2, For step 10, copy and paste doesn't work, just enter these line by line:

$ patch -p1 <<EOF
--- a/setup.py
+++ b/setup.py
@@ -9 +9 @@ _DIR = Path(__file__).parent
-_ESPEAK_DIR = _DIR / "espeak-ng" / "build"
+_ESPEAK_DIR = _DIR / "install"
@@ -13 +13 @@ _ONNXRUNTIME_DIR = _LIB_DIR / "onnxruntime"
-__version__ = "1.2.0"
+__version__ = "1.1.0"
EOF

3, I'm attaching my wheel file here, don't know why it says osx11, I'm on 14.5. piper_phonemize-1.1.0-cp311-cp311-macosx_11_0_arm64.whl.zip

williamcorney commented 6 months ago

I'm glad you got it sorted and good to know same steps works for arm64 too.

Great job :). Good to see the wheel there too.

cverrier commented 2 months ago

The solution given by @williamcorney does not work for me (macOS 14.6.1, Apple M1 Pro chip, Python 3.11.9, ZSH shell). First, I had to update Makefile (see below) due to an error with cd build && ctest --config Release:

.PHONY: all clean

all:
    cmake -Bbuild -DCMAKE_INSTALL_PREFIX=install -DCMAKE_BUILD_TYPE=Release
    cmake --build build
    cd build && ctest
    cmake --install build

clean:
    rm -rf build install

Then everything seemed to work, until I started building the wheel (step 3, 'List dependencies of piper-phonemize'): running

delocate-listdeps /Users/clementverrier/repos/piper-phonemize/dist/piper_phonemize-1.1.0-cp311-cp311-macosx_14_0_arm64.whl

led to the following output error:

ERROR:delocate.libsana:
@rpath/libespeak-ng.1.dylib not found:
  Needed by: /private/var/folders/2x/XXXXXXXX/T/tmpitpfjjp4/piper_phonemize_cpp.cpython-311-darwin.so
  Search path:

ERROR:delocate.libsana:
@rpath/libonnxruntime.1.14.1.dylib not found:
  Needed by: /private/var/folders/2x/XXXXXXXX/T/tmpitpfjjp4/piper_phonemize_cpp.cpython-311-darwin.so
  Search path:

ERROR:delocate.libsana:
@rpath/libespeak-ng.1.dylib not found:
  Needed by: /private/var/folders/2x/XXXXXXXX/T/tmpitpfjjp4/piper_phonemize_cpp.cpython-311-darwin.so
  Search path:

ERROR:delocate.libsana:@rpath/libespeak-ng.1.dylib not found, requested by /private/var/folders/2x/XXXXXXXX/T/tmpitpfjjp4/piper_phonemize_cpp.cpython-311-darwin.so
ERROR:delocate.libsana:
@rpath/libonnxruntime.1.14.1.dylib not found:
  Needed by: /private/var/folders/2x/XXXXXXXX/T/tmpitpfjjp4/piper_phonemize_cpp.cpython-311-darwin.so
  Search path:

ERROR:delocate.libsana:@rpath/libonnxruntime.1.14.1.dylib not found, requested by /private/var/folders/2x/XXXXXXXX/T/tmpitpfjjp4/piper_phonemize_cpp.cpython-311-darwin.so
/opt/homebrew/Cellar/llvm/18.1.8/lib/libunwind.1.0.dylib

I spent a consequent amount of time with an LLM trying to debug this stuff, but couldn't find a working solution so far. @bluevisor have you encountered other problems except those you mentioned?

@synesthesiam could you provide more information regarding the installation of piper via pip, including all its dependencies?