diff --git a/.editorconfig b/.editorconfig old mode 100755 new mode 100644 diff --git a/.github/workflows/external_trigger.yml b/.github/workflows/external_trigger.yml index dd6afa4..5b969f2 100644 --- a/.github/workflows/external_trigger.yml +++ b/.github/workflows/external_trigger.yml @@ -29,8 +29,8 @@ jobs: echo "> [!NOTE]" >> $GITHUB_STEP_SUMMARY echo "> External trigger running off of gpu branch. To disable this trigger, add \`piper_gpu\` into the Github organizational variable \`SKIP_EXTERNAL_TRIGGER\`." >> $GITHUB_STEP_SUMMARY printf "\n## Retrieving external version\n\n" >> $GITHUB_STEP_SUMMARY - EXT_RELEASE=$(curl -sL "https://pypi.python.org/pypi/wyoming-piper/json" |jq -r '. | .info.version') - echo "Type is \`pip_version\`" >> $GITHUB_STEP_SUMMARY + EXT_RELEASE=$(curl -u "${{ secrets.CR_USER }}:${{ secrets.CR_PAT }}" -sX GET "https://api.github.com/repos/rhasspy/wyoming-piper/commits/master" | jq -r '. | .sha' | cut -c1-8) + echo "Type is \`github_commit\`" >> $GITHUB_STEP_SUMMARY if grep -q "^piper_gpu_${EXT_RELEASE}" <<< "${SKIP_EXTERNAL_TRIGGER}"; then echo "> [!WARNING]" >> $GITHUB_STEP_SUMMARY echo "> Github organizational variable \`SKIP_EXTERNAL_TRIGGER\` matches current external release; skipping trigger." >> $GITHUB_STEP_SUMMARY diff --git a/Dockerfile b/Dockerfile index 845b8b5..ebf9af6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -12,22 +12,28 @@ LABEL maintainer="thespad" ENV DEBIAN_FRONTEND="noninteractive" \ TMPDIR="/run/piper-temp" -RUN --mount=type=bind,source=/patch,target=/patch \ +RUN \ apt-get update && \ apt-get install -y --no-install-recommends \ - build-essential \ - cmake \ - git \ - pkg-config \ - patch \ python3-venv && \ if [ -z ${PIPER_VERSION+x} ]; then \ - PIPER_VERSION=$(curl -sL https://pypi.python.org/pypi/wyoming-piper/json |jq -r '. | .info.version'); \ + PIPER_VERSION=$(curl -sL "https://api.github.com/repos/rhasspy/wyoming-piper/commits/master" \ + | jq -r .sha); \ fi && \ + mkdir -p /tmp/piper-build && \ + curl -sL -o \ + /tmp/piper.tar.gz -L \ + "https://github.com/rhasspy/wyoming-piper/archive/${PIPER_VERSION}.tar.gz" && \ + tar xzf \ + /tmp/piper.tar.gz -C \ + /tmp/piper-build --strip-components=1 && \ + cd /tmp/piper-build && \ python3 -m venv /lsiopy && \ pip install -U --no-cache-dir \ pip \ wheel && \ + pip install -U --no-cache-dir --find-links https://wheel-index.linuxserver.io/ubuntu/ . && \ + pip uninstall -y onnxruntime && \ pip install -U --no-cache-dir --find-links https://wheel-index.linuxserver.io/ubuntu/ \ nvidia-cublas-cu12 \ nvidia-cuda-nvrtc-cu12 \ @@ -36,32 +42,9 @@ RUN --mount=type=bind,source=/patch,target=/patch \ nvidia-cufft-cu12 \ nvidia-curand-cu12 \ onnxruntime-gpu \ - "wyoming-piper==${PIPER_VERSION}" && \ - if [ -z ${PIPER_BIN_VERSION+x} ]; then \ - PIPER_BIN_VERSION=$(curl -sL "https://api.github.com/repos/rhasspy/piper/commits/master" \ - | jq -r .sha); \ - fi && \ - mkdir -p /tmp/piper-build /usr/share/piper && \ - curl -sL -o \ - /tmp/piper.tar.gz -L \ - "https://github.com/rhasspy/piper/archive/${PIPER_BIN_VERSION}.tar.gz" && \ - tar xzf \ - /tmp/piper.tar.gz -C \ - /tmp/piper-build --strip-components=1 && \ - cd /tmp/piper-build && \ - cmake -Bbuild -DCMAKE_INSTALL_PREFIX=install && \ - cmake --build build --config Release && \ - cmake --install build && \ - cp -dR /tmp/piper-build/install/* /usr/share/piper && \ - patch /lsiopy/lib/python3.12/site-packages/wyoming_piper/__main__.py < /patch/__main__.patch && \ - patch /lsiopy/lib/python3.12/site-packages/wyoming_piper/process.py < /patch/process.patch && \ + piper-tts && \ printf "Linuxserver.io version: ${VERSION}\nBuild-date: ${BUILD_DATE}" > /build_version && \ echo "**** cleanup ****" && \ - apt-get purge -y \ - build-essential \ - cmake \ - git \ - pkg-config && \ apt-get autoremove -y && \ apt-get clean -y && \ rm -rf \ diff --git a/Jenkinsfile b/Jenkinsfile index 9988574..949b989 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -19,7 +19,9 @@ pipeline { DOCKERHUB_TOKEN=credentials('docker-hub-ci-pat') QUAYIO_API_TOKEN=credentials('quayio-repo-api-token') GIT_SIGNING_KEY=credentials('484fbca6-9a4f-455e-b9e3-97ac98785f5f') - EXT_PIP = 'wyoming-piper' + EXT_GIT_BRANCH = 'master' + EXT_USER = 'rhasspy' + EXT_REPO = 'wyoming-piper' BUILD_VERSION_ARG = 'PIPER_VERSION' LS_USER = 'linuxserver' LS_REPO = 'docker-piper' @@ -141,17 +143,25 @@ pipeline { /* ######################## External Release Tagging ######################## */ - // If this is a pip release set the external tag to the pip version - stage("Set ENV pip_version"){ - steps{ - script{ - env.EXT_RELEASE = sh( - script: '''curl -sL https://pypi.python.org/pypi/${EXT_PIP}/json |jq -r '. | .info.version' ''', - returnStdout: true).trim() - env.RELEASE_LINK = 'https://pypi.python.org/pypi/' + env.EXT_PIP - } - } - } // Sanitize the release tag and strip illegal docker or github characters + // If this is a github commit trigger determine the current commit at head + stage("Set ENV github_commit"){ + steps{ + script{ + env.EXT_RELEASE = sh( + script: '''curl -H "Authorization: token ${GITHUB_TOKEN}" -s https://api.github.com/repos/${EXT_USER}/${EXT_REPO}/commits/${EXT_GIT_BRANCH} | jq -r '. | .sha' | cut -c1-8 ''', + returnStdout: true).trim() + } + } + } + // If this is a github commit trigger Set the external release link + stage("Set ENV commit_link"){ + steps{ + script{ + env.RELEASE_LINK = 'https://github.com/' + env.EXT_USER + '/' + env.EXT_REPO + '/commit/' + env.EXT_RELEASE + } + } + } + // Sanitize the release tag and strip illegal docker or github characters stage("Sanitize tag"){ steps{ script{ @@ -986,7 +996,7 @@ pipeline { "tagger": {"name": "LinuxServer-CI","email": "ci@linuxserver.io","date": "'${GITHUB_DATE}'"}}' ''' echo "Pushing New release for Tag" sh '''#! /bin/bash - echo "Updating PIP version of ${EXT_PIP} to ${EXT_RELEASE_CLEAN}" > releasebody.json + curl -H "Authorization: token ${GITHUB_TOKEN}" -s https://api.github.com/repos/${EXT_USER}/${EXT_REPO}/commits/${EXT_RELEASE_CLEAN} | jq '.commit.message' | sed 's:^.\\(.*\\).$:\\1:' > releasebody.json echo '{"tag_name":"'${META_TAG}'",\ "target_commitish": "gpu",\ "name": "'${META_TAG}'",\ diff --git a/LICENSE b/LICENSE old mode 100755 new mode 100644 diff --git a/README.md b/README.md index c84b693..f8acb32 100644 --- a/README.md +++ b/README.md @@ -94,11 +94,12 @@ services: - PGID=1000 - TZ=Etc/UTC - PIPER_VOICE=en_US-lessac-medium + - LOCAL_ONLY= #optional - PIPER_LENGTH=1.0 #optional - PIPER_NOISE=0.667 #optional - PIPER_NOISEW=0.333 #optional - PIPER_SPEAKER=0 #optional - - PIPER_PROCS=1 #optional + - STREAMING= #optional volumes: - /path/to/piper/data:/config ports: @@ -115,11 +116,12 @@ docker run -d \ -e PGID=1000 \ -e TZ=Etc/UTC \ -e PIPER_VOICE=en_US-lessac-medium \ + -e LOCAL_ONLY= `#optional` \ -e PIPER_LENGTH=1.0 `#optional` \ -e PIPER_NOISE=0.667 `#optional` \ -e PIPER_NOISEW=0.333 `#optional` \ -e PIPER_SPEAKER=0 `#optional` \ - -e PIPER_PROCS=1 `#optional` \ + -e STREAMING= `#optional` \ -p 10200:10200 \ -v /path/to/piper/data:/config \ --restart unless-stopped \ @@ -137,11 +139,12 @@ Containers are configured using parameters passed at runtime (such as those abov | `-e PGID=1000` | for GroupID - see below for explanation | | `-e TZ=Etc/UTC` | specify a timezone to use, see this [list](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones#List). | | `-e PIPER_VOICE=en_US-lessac-medium` | The [Piper voice](https://huggingface.co/rhasspy/piper-voices/tree/main) to use, in the format `--` | +| `-e LOCAL_ONLY=` | If set to `true`, or any other value, the container will not attempt to download models from HuggingFace and will only use locally-provided models. | | `-e PIPER_LENGTH=1.0` | Voice speaking rate, 1.0 is default with < 1.0 being faster and > 1.0 being slower. | | `-e PIPER_NOISE=0.667` | Controls the variability of the voice by adding noise. Values above 1 will start to degrade audio. | | `-e PIPER_NOISEW=0.333` | Controls the variability of speaking cadence. Values above 1 produce extreme stutters and pauses. | | `-e PIPER_SPEAKER=0` | Speaker number to use if the voice supports multiple speakers. | -| `-e PIPER_PROCS=1` | Number of Piper processes to run simultaneously. | +| `-e STREAMING=` | Setting to `true`, or any other value, will enable support for streaming audio on sentence boundaries. | | `-v /config` | Local path for piper config files. | | `--read-only=true` | Run container with a read-only filesystem. Please [read the docs](https://docs.linuxserver.io/misc/read-only/). | @@ -307,6 +310,7 @@ Once registered you can define the dockerfile to use with `-f Dockerfile.aarch64 ## Versions +* **29.08.25:** - Add streaming support & support for local only mode. * **26.11.24:** - Add GPU branch. * **18.07.24:** - Rebase to Ubuntu Noble. * **25.11.23:** - Initial Release. diff --git a/jenkins-vars.yml b/jenkins-vars.yml index 8d5360c..2d6da72 100644 --- a/jenkins-vars.yml +++ b/jenkins-vars.yml @@ -2,12 +2,14 @@ # jenkins variables project_name: docker-piper -external_type: pip_version +external_type: github_commit release_type: prerelease release_tag: gpu ls_branch: gpu repo_vars: - - EXT_PIP = 'wyoming-piper' + - EXT_GIT_BRANCH = 'master' + - EXT_USER = 'rhasspy' + - EXT_REPO = 'wyoming-piper' - BUILD_VERSION_ARG = 'PIPER_VERSION' - LS_USER = 'linuxserver' - LS_REPO = 'docker-piper' diff --git a/patch/__main__.patch b/patch/__main__.patch deleted file mode 100644 index 53cb972..0000000 --- a/patch/__main__.patch +++ /dev/null @@ -1,14 +0,0 @@ ---- __main__-old.py 2024-11-26 16:26:59.644200503 +0000 -+++ __main__.py 2024-11-26 16:19:53.459497442 +0000 -@@ -65,6 +65,11 @@ - action="store_true", - help="Download latest voices.json during startup", - ) -+ parser.add_argument( -+ "--cuda", -+ action="store_true", -+ help="Use GPU" -+ ) - # - parser.add_argument("--debug", action="store_true", help="Log DEBUG messages") - args = parser.parse_args() diff --git a/patch/process.patch b/patch/process.patch deleted file mode 100644 index 269d965..0000000 --- a/patch/process.patch +++ /dev/null @@ -1,12 +0,0 @@ ---- process-old.py 2024-11-26 16:20:27.856796223 +0000 -+++ process.py 2024-11-26 16:19:40.522385074 +0000 -@@ -148,6 +148,9 @@ - if self.args.noise_w: - piper_args.extend(["--noise-w", str(self.args.noise_w)]) - -+ if self.args.cuda: -+ piper_args.extend(["--cuda"]) -+ - _LOGGER.debug( - "Starting piper process: %s args=%s", self.args.piper, piper_args - ) diff --git a/readme-vars.yml b/readme-vars.yml index 65532bf..b937c1b 100644 --- a/readme-vars.yml +++ b/readme-vars.yml @@ -28,11 +28,12 @@ param_ports: # optional container parameters opt_param_usage_include_env: true opt_param_env_vars: + - {env_var: "LOCAL_ONLY", env_value: "", desc: "If set to `true`, or any other value, the container will not attempt to download models from HuggingFace and will only use locally-provided models."} - {env_var: "PIPER_LENGTH", env_value: "1.0", desc: "Voice speaking rate, 1.0 is default with < 1.0 being faster and > 1.0 being slower."} - {env_var: "PIPER_NOISE", env_value: "0.667", desc: "Controls the variability of the voice by adding noise. Values above 1 will start to degrade audio."} - {env_var: "PIPER_NOISEW", env_value: "0.333", desc: "Controls the variability of speaking cadence. Values above 1 produce extreme stutters and pauses."} - {env_var: "PIPER_SPEAKER", env_value: "0", desc: "Speaker number to use if the voice supports multiple speakers."} - - {env_var: "PIPER_PROCS", env_value: "1", desc: "Number of Piper processes to run simultaneously."} + - {env_var: "STREAMING", env_value: "", desc: "Setting to `true`, or any other value, will enable support for streaming audio on sentence boundaries."} readonly_supported: true # application setup block app_setup_block_enabled: true @@ -85,6 +86,7 @@ init_diagram: | "piper:gpu" <- Base Images # changelog changelogs: + - {date: "29.08.25:", desc: "Add streaming support & support for local only mode."} - {date: "26.11.24:", desc: "Add GPU branch."} - {date: "18.07.24:", desc: "Rebase to Ubuntu Noble."} - {date: "25.11.23:", desc: "Initial Release."} diff --git a/root/etc/s6-overlay/s6-rc.d/svc-piper/run b/root/etc/s6-overlay/s6-rc.d/svc-piper/run index 362c32d..a5b8c00 100755 --- a/root/etc/s6-overlay/s6-rc.d/svc-piper/run +++ b/root/etc/s6-overlay/s6-rc.d/svc-piper/run @@ -9,19 +9,25 @@ for dir in "${NVIDIA_PACKAGE_DIR}"/*; do fi done +unset UPDATE_MODELS + +if [[ -z ${LOCAL_ONLY} ]]; then + UPDATE_MODELS=true +fi + LD_LIBRARY_PATH="/lsiopy/lib/python3.12/site-packages/onnxruntime/capi:$LD_LIBRARY_PATH" exec \ s6-notifyoncheck -d -n 300 -w 1000 -c "nc -z localhost 10200" \ s6-setuidgid abc python3 -m wyoming_piper \ - --piper '/usr/share/piper/piper' \ --uri 'tcp://0.0.0.0:10200' \ --length-scale "${PIPER_LENGTH:-1.0}" \ --noise-scale "${PIPER_NOISE:-0.667}" \ --noise-w "${PIPER_NOISEW:-0.333}" \ --speaker "${PIPER_SPEAKER:-0}" \ --voice "${PIPER_VOICE}" \ - --max-piper-procs "${PIPER_PROCS:-1}" \ --data-dir /config \ - --download-dir /config --update-voices \ - --cuda + --download-dir /config \ + --use-cuda \ + ${UPDATE_MODELS:+--update-voices} \ + ${STREAMING:+--streaming}