diff --git a/.gitignore b/.gitignore index 79420be..5573f10 100644 --- a/.gitignore +++ b/.gitignore @@ -13,4 +13,5 @@ dist/ *.wav *.spec -/samples +/samples/ +/voices/ diff --git a/Dockerfile b/Dockerfile index 9036121..e189793 100644 --- a/Dockerfile +++ b/Dockerfile @@ -40,13 +40,20 @@ RUN --mount=type=cache,id=apt-build,target=/var/cache/apt \ WORKDIR /home/mimic3/app -COPY ./ ./ +COPY opentts-abc/ ./opentts-abc/ +COPY mimic3-http/ ./mimic3-http/ +COPY mimic3-tts/ ./mimic3-tts/ +COPY install.sh ./ # Install mimic3 RUN --mount=type=cache,id=pip-requirements,target=/root/.cache/pip \ PIP_INSTALL='install -f https://synesthesiam.github.io/prebuilt-apps/' \ ./install.sh +# Download default voice +COPY voices/ /root/.local/share/mimic3/voices/ +RUN .venv/bin/mimic3-download 'en_UK/apope_low' + # ----------------------------------------------------------------------------- FROM debian:bullseye as run @@ -62,16 +69,32 @@ RUN --mount=type=cache,id=apt-run,target=/var/cache/apt \ mkdir -p /var/cache/apt/${TARGETARCH}${TARGETVARIANT}/archives/partial && \ apt-get update && \ apt-get install --yes --no-install-recommends \ - python3 ca-certificates libespeak-ng1 + python3 ca-certificates libespeak-ng1 libatomic1 libgomp1 RUN useradd -ms /bin/bash mimic3 # Copy virtual environment and source code COPY --from=build /home/mimic3/app/ /home/mimic3/app/ -USER mimic3 +# Copy pre-downloaded voice(s) +COPY --from=build /root/.local/share/mimic3/voices/ /usr/share/mimic3/voices/ + WORKDIR /home/mimic3/app +# Run test +COPY tests/apope_sample.txt tests/apope_sample_*.wav tests/ + +# Generate sample and check +RUN export expected_sample="tests/apope_sample_${TARGETARCH}${TARGETVARIANT}.wav" && \ + .venv/bin/mimic3 \ + --deterministic \ + --voice 'en_UK/apope_low' \ + < tests/apope_sample.txt \ + > tests/actual_sample.wav && \ + diff tests/actual_sample.wav "${expected_sample}" + +USER mimic3 + EXPOSE 59125 ENTRYPOINT ["/home/mimic3/app/.venv/bin/python3", "-m", "mimic3_http"] diff --git a/Dockerfile.debian b/Dockerfile.debian new file mode 100644 index 0000000..19ec8d7 --- /dev/null +++ b/Dockerfile.debian @@ -0,0 +1,189 @@ +# Copyright 2022 Mycroft AI Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +# ----------------------------------------------------------------------------- +# Dockerfile for Mimic 3 (https://github.com/MycroftAI/mimic3) +# +# Creates self-contained binaries using PyInstaller +# (https://pyinstaller.readthedocs.io/en/stable/). +# +# Packages into a Debian (.deb) package. +# +# Requires Docker buildx: https://docs.docker.com/buildx/working-with-buildx/ +# ----------------------------------------------------------------------------- + +FROM debian:bullseye as build +ARG TARGETARCH +ARG TARGETVARIANT + +ENV LANG C.UTF-8 +ENV DEBIAN_FRONTEND=noninteractive + +RUN echo "Dir::Cache var/cache/apt/${TARGETARCH}${TARGETVARIANT};" > /etc/apt/apt.conf.d/01cache + +RUN --mount=type=cache,id=apt-build,target=/var/cache/apt \ + mkdir -p /var/cache/apt/${TARGETARCH}${TARGETVARIANT}/archives/partial && \ + apt-get update && \ + apt-get install --yes --no-install-recommends \ + python3 python3-pip python3-venv \ + build-essential python3-dev \ + libespeak-ng1 dpkg-dev rsync gettext-base + +WORKDIR /build/mimic3 + +COPY opentts-abc/ ./opentts-abc/ +COPY mimic3-http/ ./mimic3-http/ +COPY mimic3-tts/ ./mimic3-tts/ +COPY install.sh ./ + +# Install mimic3 +RUN --mount=type=cache,id=pip-venv,target=/root/.cache/pip \ + PIP_INSTALL='install -f https://synesthesiam.github.io/prebuilt-apps/' \ + ./install.sh + +# Install PyInstaller +RUN --mount=type=cache,id=pip-venv,target=/root/.cache/pip \ + .venv/bin/pip3 install 'pyinstaller>=4,<5' + +COPY pyinstaller/mimic3.py ./pyinstaller/ + +# Create binary +RUN .venv/bin/pyinstaller \ + --noconfirm \ + --name mimic3 \ + --hidden-import 'pycrfsuite._dumpparser' \ + --hidden-import 'pycrfsuite._logparser' \ + --collect-binaries 'onnxruntime' \ + --collect-data 'gruut' \ + --hidden-import "gruut_lang_de" \ + --collect-data "gruut_lang_de" \ + --hidden-import "gruut_lang_en" \ + --collect-data "gruut_lang_en" \ + --hidden-import "gruut_lang_es" \ + --collect-data "gruut_lang_es" \ + --hidden-import "gruut_lang_fr" \ + --collect-data "gruut_lang_fr" \ + --hidden-import "gruut_lang_it" \ + --collect-data "gruut_lang_it" \ + --hidden-import "gruut_lang_nl" \ + --collect-data "gruut_lang_nl" \ + --hidden-import "gruut_lang_ru" \ + --collect-data "gruut_lang_ru" \ + --hidden-import "gruut_lang_sw" \ + --collect-data "gruut_lang_sw" \ + --hidden-import "gruut_lang_fa" \ + --collect-data "gruut_lang_fa" \ + --collect-data 'espeak_phonemizer' \ + --collect-data 'phonemes2ids' \ + --hidden-import 'swagger_ui' \ + --hidden-import 'epitran' \ + --hidden-import 'hazm' \ + --collect-data 'hazm' \ + --collect-data 'panphon' \ + --collect-data 'mimic3_tts' \ + --collect-data 'mimic3_http' \ + pyinstaller/mimic3.py + +# Have to manually copy these over for some reason +RUN find .venv -name 'wapiti' -type d -exec cp -R {} dist/mimic3/ \; +RUN find .venv -name 'libwapiti.*.so' -type f -exec cp {} dist/mimic3/ \; + +# Clean up unused lexicons +RUN find dist/mimic3/ -wholename '*/gruut_lang_*/espeak' -type d | \ + while read -r espeak_dir; do \ + rm -rf "${espeak_dir}"; \ + done + +# Copy convenience scripts +COPY pyinstaller/mimic3-server \ + pyinstaller/mimic3-download \ + dist/mimic3/ + +# Create Debian package +ENV package_dir=/package/mimic3-tts + +COPY debian/ debian/ +COPY voices/ voices/ + +RUN mkdir -p "${package_dir}/DEBIAN" && \ + export VERSION="$(cat mimic3-tts/mimic3_tts/VERSION)" && \ + export DEBIAN_ARCH="$(dpkg-architecture | grep '^DEB_HOST_ARCH=' | sed -e 's/^.\+=//')" && \ + envsubst \ + < "debian/control.in" \ + > "${package_dir}/DEBIAN/control" && \ + mkdir -p "${package_dir}/usr/lib/mimic3-tts" && \ + rsync -av "dist/mimic3/" "${package_dir}/usr/lib/mimic3-tts/" && \ + mkdir -p "${package_dir}/usr/bin/" && \ + rsync -av "debian/bin/" "${package_dir}/usr/bin/" && \ + export dest_voice_dir="${package_dir}/usr/share/mimic3/voices/en_UK/apope_low" && \ + mkdir -p "${dest_voice_dir}" && \ + rsync -av "voices/en_UK/apope_low/" "${dest_voice_dir}/" && \ + cd /package && \ + dpkg --build 'mimic3-tts' && \ + dpkg-name ./*.deb + +# ----------------------------------------------------------------------------- + +FROM debian:bullseye as test +ARG TARGETARCH +ARG TARGETVARIANT + +ENV LANG C.UTF-8 +ENV DEBIAN_FRONTEND=noninteractive + +RUN echo "Dir::Cache var/cache/apt/${TARGETARCH}${TARGETVARIANT};" > /etc/apt/apt.conf.d/01cache + +RUN --mount=type=cache,id=apt-run,target=/var/cache/apt \ + mkdir -p /var/cache/apt/${TARGETARCH}${TARGETVARIANT}/archives/partial && \ + apt-get update && \ + apt-get install --yes --no-install-recommends \ + dpkg-dev + +WORKDIR /test + +COPY --from=build /package/*.deb ./ +COPY mimic3-tts/mimic3_tts/VERSION ./ + +# Install mimic3 for current architecture +RUN --mount=type=cache,id=apt-run,target=/var/cache/apt \ + export mimic3_version="$(cat VERSION)" && \ + dpkg-architecture | \ + grep 'DEB_HOST_ARCH=' | \ + sed -e 's/.\+=//' | \ + xargs printf "./mimic3-tts_${mimic3_version}_%s.deb" | \ + xargs apt install --yes + +# Run test +COPY tests/apope_sample.txt tests/apope_sample_*.wav tests/ + +# Generate sample and check +RUN export expected_sample="tests/apope_sample_${TARGETARCH}${TARGETVARIANT}.wav" && \ + mimic3 \ + --deterministic \ + --voice 'en_UK/apope_low' \ + < tests/apope_sample.txt \ + > tests/actual_sample.wav && \ + diff tests/actual_sample.wav "${expected_sample}" + +# ----------------------------------------------------------------------------- + +FROM scratch +ARG TARGETARCH +ARG TARGETVARIANT + +COPY --from=build /package/*.deb / + +# Ensure test runs +COPY --from=test /test/tests/actual_sample.wav "/apope_sample_${TARGETARCH}${TARGETVARIANT}.wav" diff --git a/Dockerfile.debian.dockerignore b/Dockerfile.debian.dockerignore new file mode 100644 index 0000000..db3b6e2 --- /dev/null +++ b/Dockerfile.debian.dockerignore @@ -0,0 +1,42 @@ +* +!install.sh +!pyinstaller/*.py +!pyinstaller/mimic3-server +!pyinstaller/mimic3-download +!tests/apope_sample.txt +!tests/apope_sample_*.wav +!voices/ + +# Debian packaging +!debian/control.in +!debian/bin/* + +# opentts-abc +!opentts-abc/setup.py +!opentts-abc/LICENSE +!opentts-abc/MANIFEST.in +!opentts-abc/opentts_abc/*.py +!opentts-abc/opentts_abc/VERSION +!opentts-abc/opentts_abc/py.typed + +# Mimic 3 TTS +!mimic3-tts/setup.py +!mimic3-tts/LICENSE +!mimic3-tts/MANIFEST.in +!mimic3-tts/requirements.txt +!mimic3-tts/mimic3_tts/*.py +!mimic3-tts/mimic3_tts/voices.json +!mimic3-tts/mimic3_tts/VERSION +!mimic3-tts/mimic3_tts/py.typed + +# HTTP server +!mimic3-http/setup.py +!mimic3-http/LICENSE +!mimic3-http/MANIFEST.in +!mimic3-http/requirements.txt +!mimic3-http/mimic3_http/css/ +!mimic3-http/mimic3_http/img/ +!mimic3-http/mimic3_http/templates/ +!mimic3-http/mimic3_http/*.py +!mimic3-http/mimic3_http/VERSION +!mimic3-http/mimic3_http/py.typed diff --git a/Dockerfile.dist b/Dockerfile.dist index 4de18ff..4877fe5 100644 --- a/Dockerfile.dist +++ b/Dockerfile.dist @@ -16,27 +16,88 @@ # ----------------------------------------------------------------------------- # Dockerfile for Mimic 3 (https://github.com/MycroftAI/mimic3) # -# Runs code checks and creates source code distributions for PyPI. +# Creates source code distributions for PyPI. # # Requires Docker buildx: https://docs.docker.com/buildx/working-with-buildx/ # ----------------------------------------------------------------------------- -FROM python:3.9 - +FROM debian:bullseye as build ARG TARGETARCH ARG TARGETVARIANT ENV LANG C.UTF-8 ENV DEBIAN_FRONTEND=noninteractive +RUN echo "Dir::Cache var/cache/apt/${TARGETARCH}${TARGETVARIANT};" > /etc/apt/apt.conf.d/01cache + +RUN --mount=type=cache,id=apt-build,target=/var/cache/apt \ + mkdir -p /var/cache/apt/${TARGETARCH}${TARGETVARIANT}/archives/partial && \ + apt-get update && \ + apt-get install --yes --no-install-recommends \ + python3 python3-venv python3-pip + WORKDIR /build/mimic3 -COPY ./ ./ -# Install mimic3 and development dependencies -RUN --mount=type=cache,id=pip-venv,target=/root/.cache/pip \ - ./install.sh develop - -# Check code -RUN ./check.sh +COPY opentts-abc/ ./opentts-abc/ +COPY mimic3-http/ ./mimic3-http/ +COPY mimic3-tts/ ./mimic3-tts/ +COPY build-dist.sh ./ # Create sdists RUN ./build-dist.sh + +# ----------------------------------------------------------------------------- + +FROM debian:bullseye as test +ARG TARGETARCH +ARG TARGETVARIANT + +ENV LANG C.UTF-8 +ENV DEBIAN_FRONTEND=noninteractive + +RUN echo "Dir::Cache var/cache/apt/${TARGETARCH}${TARGETVARIANT};" > /etc/apt/apt.conf.d/01cache + +RUN --mount=type=cache,id=apt-run,target=/var/cache/apt \ + mkdir -p /var/cache/apt/${TARGETARCH}${TARGETVARIANT}/archives/partial && \ + apt-get update && \ + apt-get install --yes --no-install-recommends \ + python3 python3-venv python3-pip \ + libespeak-ng1 libatomic1 libgomp1 + +WORKDIR /test + +COPY --from=build /build/mimic3/dist/*.tar.gz ./dist/ + +# Install mimic3 using source distribution +RUN --mount=type=cache,id=pip-requirements,target=/root/.cache/pip \ + python3 -m venv .venv && \ + .venv/bin/pip3 install \ + -f https://synesthesiam.github.io/prebuilt-apps/ \ + -f dist/ \ + mimic3-tts + +# Download default voice +COPY voices/ /root/.local/share/mimic3/voices/ +RUN .venv/bin/mimic3-download 'en_UK/apope_low' + +# Run test +COPY tests/apope_sample.txt tests/apope_sample_*.wav tests/ + +# Generate sample and check +RUN export expected_sample="tests/apope_sample_${TARGETARCH}${TARGETVARIANT}.wav" && \ + .venv/bin/mimic3 \ + --deterministic \ + --voice 'en_UK/apope_low' \ + < tests/apope_sample.txt \ + > tests/actual_sample.wav && \ + diff tests/actual_sample.wav "${expected_sample}" + +# ----------------------------------------------------------------------------- + +FROM scratch +ARG TARGETARCH +ARG TARGETVARIANT + +COPY --from=build /build/mimic3/dist/*.tar.gz / + +# Ensure test runs +COPY --from=test /test/tests/actual_sample.wav "/apope_sample_${TARGETARCH}${TARGETVARIANT}.wav" diff --git a/Dockerfile.dist.dockerignore b/Dockerfile.dist.dockerignore new file mode 100644 index 0000000..9d96d09 --- /dev/null +++ b/Dockerfile.dist.dockerignore @@ -0,0 +1,35 @@ +* +!build-dist.sh +!tests/apope_sample.txt +!tests/apope_sample_*.wav +!voices/ + +# opentts-abc +!opentts-abc/setup.py +!opentts-abc/LICENSE +!opentts-abc/MANIFEST.in +!opentts-abc/opentts_abc/*.py +!opentts-abc/opentts_abc/VERSION +!opentts-abc/opentts_abc/py.typed + +# Mimic 3 TTS +!mimic3-tts/setup.py +!mimic3-tts/LICENSE +!mimic3-tts/MANIFEST.in +!mimic3-tts/requirements.txt +!mimic3-tts/mimic3_tts/*.py +!mimic3-tts/mimic3_tts/voices.json +!mimic3-tts/mimic3_tts/VERSION +!mimic3-tts/mimic3_tts/py.typed + +# HTTP server +!mimic3-http/setup.py +!mimic3-http/LICENSE +!mimic3-http/MANIFEST.in +!mimic3-http/requirements.txt +!mimic3-http/mimic3_http/css/ +!mimic3-http/mimic3_http/img/ +!mimic3-http/mimic3_http/templates/ +!mimic3-http/mimic3_http/*.py +!mimic3-http/mimic3_http/VERSION +!mimic3-http/mimic3_http/py.typed diff --git a/Dockerfile.dockerignore b/Dockerfile.dockerignore new file mode 100644 index 0000000..6afb7f8 --- /dev/null +++ b/Dockerfile.dockerignore @@ -0,0 +1,35 @@ +* +!install.sh +!tests/apope_sample.txt +!tests/apope_sample_*.wav +!voices/ + +# opentts-abc +!opentts-abc/setup.py +!opentts-abc/LICENSE +!opentts-abc/MANIFEST.in +!opentts-abc/opentts_abc/*.py +!opentts-abc/opentts_abc/VERSION +!opentts-abc/opentts_abc/py.typed + +# Mimic 3 TTS +!mimic3-tts/setup.py +!mimic3-tts/LICENSE +!mimic3-tts/MANIFEST.in +!mimic3-tts/requirements.txt +!mimic3-tts/mimic3_tts/*.py +!mimic3-tts/mimic3_tts/voices.json +!mimic3-tts/mimic3_tts/VERSION +!mimic3-tts/mimic3_tts/py.typed + +# HTTP server +!mimic3-http/setup.py +!mimic3-http/LICENSE +!mimic3-http/MANIFEST.in +!mimic3-http/requirements.txt +!mimic3-http/mimic3_http/css/ +!mimic3-http/mimic3_http/img/ +!mimic3-http/mimic3_http/templates/ +!mimic3-http/mimic3_http/*.py +!mimic3-http/mimic3_http/VERSION +!mimic3-http/mimic3_http/py.typed diff --git a/Dockerfile.sample b/Dockerfile.sample new file mode 100644 index 0000000..bd918e4 --- /dev/null +++ b/Dockerfile.sample @@ -0,0 +1,71 @@ +# Copyright 2022 Mycroft AI Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +# ----------------------------------------------------------------------------- +# Dockerfile for Mimic 3 (https://github.com/MycroftAI/mimic3) +# +# Generates a deterministic sample WAV used for testing. +# +# Requires Docker buildx: https://docs.docker.com/buildx/working-with-buildx/ +# ----------------------------------------------------------------------------- + +FROM debian:bullseye as build +ARG TARGETARCH +ARG TARGETVARIANT + +ENV LANG C.UTF-8 +ENV DEBIAN_FRONTEND=noninteractive + +RUN echo "Dir::Cache var/cache/apt/${TARGETARCH}${TARGETVARIANT};" > /etc/apt/apt.conf.d/01cache + +RUN --mount=type=cache,id=apt-build,target=/var/cache/apt \ + mkdir -p /var/cache/apt/${TARGETARCH}${TARGETVARIANT}/archives/partial && \ + apt-get update && \ + apt-get install --yes --no-install-recommends \ + python3 python3-pip python3-venv \ + build-essential python3-dev + +WORKDIR /home/mimic3/app + +COPY opentts-abc/ ./opentts-abc/ +COPY mimic3-http/ ./mimic3-http/ +COPY mimic3-tts/ ./mimic3-tts/ +COPY install.sh ./ + +# Install mimic3 +RUN --mount=type=cache,id=pip-requirements,target=/root/.cache/pip \ + PIP_INSTALL='install -f https://synesthesiam.github.io/prebuilt-apps/' \ + ./install.sh + +# Download default voice +COPY voices/ /root/.local/share/mimic3/voices/ +RUN .venv/bin/mimic3-download 'en_UK/apope_low' + +# Generate sample +COPY tests/apope_sample.txt tests/ + +# Generate sample and check +RUN export expected_sample="tests/apope_sample_${TARGETARCH}${TARGETVARIANT}.wav" && \ + .venv/bin/mimic3 \ + --deterministic \ + --voice 'en_UK/apope_low' \ + < tests/apope_sample.txt \ + > "tests/apope_sample_${TARGETARCH}${TARGETVARIANT}.wav" + +# ----------------------------------------------------------------------------- + +FROM scratch + +COPY --from=build /home/mimic3/app/tests/apope_sample_*.wav ./ diff --git a/Dockerfile.sample.dockerignore b/Dockerfile.sample.dockerignore new file mode 100644 index 0000000..07725eb --- /dev/null +++ b/Dockerfile.sample.dockerignore @@ -0,0 +1,34 @@ +* +!install.sh +!tests/apope_sample.txt +!voices/ + +# opentts-abc +!opentts-abc/setup.py +!opentts-abc/LICENSE +!opentts-abc/MANIFEST.in +!opentts-abc/opentts_abc/*.py +!opentts-abc/opentts_abc/VERSION +!opentts-abc/opentts_abc/py.typed + +# Mimic 3 TTS +!mimic3-tts/setup.py +!mimic3-tts/LICENSE +!mimic3-tts/MANIFEST.in +!mimic3-tts/requirements.txt +!mimic3-tts/mimic3_tts/*.py +!mimic3-tts/mimic3_tts/voices.json +!mimic3-tts/mimic3_tts/VERSION +!mimic3-tts/mimic3_tts/py.typed + +# HTTP server +!mimic3-http/setup.py +!mimic3-http/LICENSE +!mimic3-http/MANIFEST.in +!mimic3-http/requirements.txt +!mimic3-http/mimic3_http/css/ +!mimic3-http/mimic3_http/img/ +!mimic3-http/mimic3_http/templates/ +!mimic3-http/mimic3_http/*.py +!mimic3-http/mimic3_http/VERSION +!mimic3-http/mimic3_http/py.typed diff --git a/Makefile b/Makefile index 670cc30..af9c995 100644 --- a/Makefile +++ b/Makefile @@ -13,38 +13,53 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . # -.PHONY: dist install docker binaries +.PHONY: dist install docker docker-gpu debian sample SHELL := bash # linux/amd64,linux/arm64,linux/arm/v7 DOCKER_PLATFORM ?= linux/amd64 DOCKER_OUTPUT ?= --load +DOCKER_TAG ?= mycroftai/mimic3 +# Build source distributions for PyPI. +# Also tests installation. dist: - ./build-dist.sh + echo "$(DOCKER_PLATFORM)" | sed -e 's/,/\n/g' | \ + while read -r platform; do \ + docker buildx build . -f Dockerfile.dist --platform $(DOCKER_PLATFORM) --output "type=local,dest=dist/"; \ + done +# Create virtual environment and install in editable mode locally. install: ./install.sh +# Create self-contained Docker image. +# Also tests functionality. docker: - docker buildx build . -f Dockerfile --platform $(DOCKER_PLATFORM) --tag mycroftai/mimic3 $(DOCKER_OUTPUT) + echo "$(DOCKER_PLATFORM)" | sed -e 's/,/\n/g' | \ + while read -r platform; do \ + docker buildx build . -f Dockerfile --platform $(DOCKER_PLATFORM) --tag "$(DOCKER_TAG)" $(DOCKER_OUTPUT); \ + done +# Create self-container Docker image with GPU support. +# Requires nvidia-docker. docker-gpu: - docker buildx build . -f Dockerfile.gpu --tag 'mycroftai/mimic3:gpu' $(DOCKER_OUTPUT) + docker buildx build . -f Dockerfile.gpu --tag "$(DOCKER_TAG):gpu" $(DOCKER_OUTPUT) -binaries: +# Create sample WAV files that are elsewhere for testing. +# These are different per platform (amd64, etc.). +# It's critical that deterministic mode is used to generate and test. +sample: echo "$(DOCKER_PLATFORM)" | sed -e 's/,/\n/g' | \ while read -r platform; do \ - rm -rf "dist/$${platform}"; \ - docker buildx build . -f Dockerfile.binary --platform "$${platform}" --output "type=local,dest=dist/$${platform}"; \ + docker buildx build . -f Dockerfile.sample --platform $(DOCKER_PLATFORM) --output "type=local,dest=tests/"; \ done +# Create Debian packages (packaged with apope voice). +# Also tests installation. debian: - debian/build-debian.sh - -test: echo "$(DOCKER_PLATFORM)" | sed -e 's/,/\n/g' | \ while read -r platform; do \ - docker buildx build . -f Dockerfile.test --platform "$${platform}"; \ + docker buildx build . -f Dockerfile.debian --platform $(DOCKER_PLATFORM) --output "type=local,dest=dist/"; \ done diff --git a/debian/control.in b/debian/control.in index 6518e3c..4e8769a 100644 --- a/debian/control.in +++ b/debian/control.in @@ -2,7 +2,7 @@ Package: mimic3-tts Version: ${VERSION} Section: utils Priority: optional -Depends: libespeak-ng1 +Depends: libespeak-ng1 libatomic1 libgomp1 Recommends: sox Architecture: ${DEBIAN_ARCH} Maintainer: Mycroft AI diff --git a/mimic3-tts/mimic3_tts/voices.json b/mimic3-tts/mimic3_tts/voices.json index 9e02338..81f3161 100644 --- a/mimic3-tts/mimic3_tts/voices.json +++ b/mimic3-tts/mimic3_tts/voices.json @@ -1,5 +1,5 @@ { - "af_ZA/google_nwu": { + "af_ZA/google-nwu_low": { "files": { "LICENSE": { "size_bytes": 56, @@ -14,8 +14,8 @@ "sha256_sum": "8a9a0d5d775c0264004b68c4ca850fd51c3d8e63cdbc9df61ec257a3ee97e025" }, "config.json": { - "size_bytes": 3881, - "sha256_sum": "3f7c44b4ad3ca0bd5aad619f9920d25676f8b02f8a936b9c84fcaa272c0b0935" + "size_bytes": 3915, + "sha256_sum": "484c3ba1581274b63f19e8eae0aa0533fe731136f5f75af0e68159b4f4567896" }, "generator.onnx": { "size_bytes": 76351329, @@ -1223,6 +1223,51 @@ "speakers": [], "properties": {} }, + "pl_PL/m-ailabs_low": { + "files": { + "ALIASES": { + "size_bytes": 15, + "sha256_sum": "87d98f3b3b5eaae7d5acb11d3781eabe06a8ef4ef0c446a1499d4f9ad9230c84" + }, + "LICENSE": { + "size_bytes": 1372, + "sha256_sum": "fdd78a909fb9384d869363522b967557bc9e28e5b65874921f24e48cbb82f38c" + }, + "README.md": { + "size_bytes": 192, + "sha256_sum": "b78139a85d9fb800852437309e81bc214287365a5adc388a9200f6520c7a249b" + }, + "SOURCE": { + "size_bytes": 61, + "sha256_sum": "841520f6a8cc616e307a92552355691f8c3087fadda2e9b7a03a7863b2d0cf6a" + }, + "config.json": { + "size_bytes": 3635, + "sha256_sum": "bb120183dd6153b2e5851e9af7daddf074d8a468314ad98928a1354611907b4c" + }, + "generator.onnx": { + "size_bytes": 76326239, + "sha256_sum": "5e19ef55e499664648205ee059d0cf79fb1532c2263c12365cd64508a86cada9" + }, + "phonemes.txt": { + "size_bytes": 244, + "sha256_sum": "c1fcdbb56a3a00ec1cdeccfb0ec5ef84b4539ae1d8a5fead1872caa4364aa4f4" + }, + "speaker_map.csv": { + "size_bytes": 47, + "sha256_sum": "c1136cf577345e40f67fa63d24eac9db89b4cb675bd1c646a5c3a4e9243ac76f" + }, + "speakers.txt": { + "size_bytes": 23, + "sha256_sum": "32b36232b632bad2f0fb04cee37c2d1164332ff6bf5c2b4a0ae64657761b01af" + } + }, + "speakers": [ + "piotr_nater", + "nina_brown" + ], + "properties": {} + }, "ru_RU/multi_low": { "files": { "ALIASES": { @@ -1361,6 +1406,71 @@ ], "properties": {} }, + "tn_ZA/google-nwu_low": { + "files": { + "LICENSE": { + "size_bytes": 56, + "sha256_sum": "9de32c12fbae55d90964a887d50116a3369962799532fcd7663d32f55c1945fe" + }, + "README.md": { + "size_bytes": 184, + "sha256_sum": "8f55845c87eb5f01af3cf686247ca3807c94e27cb3a021c8f5a61eb40bfb4ecc" + }, + "SOURCE": { + "size_bytes": 27, + "sha256_sum": "8a9a0d5d775c0264004b68c4ca850fd51c3d8e63cdbc9df61ec257a3ee97e025" + }, + "config.json": { + "size_bytes": 3885, + "sha256_sum": "169a746efc5836d4cdc5aecbae7347e0dcdab070e29511afd56a2471d9f5ac7d" + }, + "generator.onnx": { + "size_bytes": 76376929, + "sha256_sum": "556648cbcc83acd896919bc9e2a7e0ca3d64ab9a411307ccd5584af2bc5b4391" + }, + "phonemes.txt": { + "size_bytes": 252, + "sha256_sum": "b8974c85be943cbd25dc4de58e42b69ddb0c67812b5f8b269f9ca22a1355bdcf" + }, + "speaker_map.csv": { + "size_bytes": 562, + "sha256_sum": "ed50cf529d8332c032756ed11b8ebbd31e46186cdd79f0dfa3768f356832a65e" + }, + "speakers.txt": { + "size_bytes": 130, + "sha256_sum": "bf0e54741d96aba0c3862feffe63b658f3b2f2de60377a78c18546e2d7f69bf9" + } + }, + "speakers": [ + "1932", + "0045", + "3342", + "4850", + "6206", + "3629", + "9061", + "6116", + "7674", + "0378", + "5628", + "8333", + "8512", + "0441", + "6459", + "4506", + "7866", + "8532", + "2839", + "7896", + "1498", + "1483", + "8914", + "6234", + "9365", + "7693" + ], + "properties": {} + }, "uk_UK/m-ailabs_low": { "files": { "ALIASES": { diff --git a/tests/Dockerfile.test.debian b/tests/Dockerfile.test.debian new file mode 100644 index 0000000..f744a43 --- /dev/null +++ b/tests/Dockerfile.test.debian @@ -0,0 +1,75 @@ +# Copyright 2022 Mycroft AI Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +# ----------------------------------------------------------------------------- +# Dockerfile for Mimic 3 (https://github.com/MycroftAI/mimic3) +# +# Tests installation and functionality of Mimic 3 Debian package. +# +# Requires Docker buildx: https://docs.docker.com/buildx/working-with-buildx/ +# ----------------------------------------------------------------------------- +FROM debian:bullseye as test + +ARG TARGETARCH +ARG TARGETVARIANT + +ENV LANG C.UTF-8 +ENV DEBIAN_FRONTEND=noninteractive + +RUN echo "Dir::Cache var/cache/apt/${TARGETARCH}${TARGETVARIANT};" > /etc/apt/apt.conf.d/01cache + +RUN --mount=type=cache,id=apt-run,target=/var/cache/apt \ + mkdir -p /var/cache/apt/${TARGETARCH}${TARGETVARIANT}/archives/partial && \ + apt-get update && \ + apt-get install --yes --no-install-recommends \ + dpkg-dev + +WORKDIR /test + +COPY dist/*.deb ./ +COPY mimic3-tts/mimic3_tts/VERSION ./ + +# Install mimic3 for current architecture +RUN --mount=type=cache,id=apt-run,target=/var/cache/apt \ + export mimic3_version="$(cat VERSION)" && \ + dpkg-architecture | \ + grep 'DEB_HOST_ARCH=' | \ + sed -e 's/.\+=//' | \ + xargs printf "./mimic3-tts_${mimic3_version}_%s.deb" | \ + xargs apt install --yes + +# Version check +RUN export expected_version="$(cat VERSION)" && \ + export actual_version="$(mimic3 --version)" && \ + if [ ! "${expected_version}" = "${actual_version}"]; then \ + echo "${actual_version} != ${expected_version}"; \ + exit 1; \ + fi + +# Generate sample and check +COPY tests/apope_sample.* ./ +RUN mimic3 \ + --deterministic \ + --voice 'en_UK/apope_low' \ + < apope_sample.txt \ + > actual_sample.wav + +# RUN diff apope_sample.wav actual_sample.wav + +# ----------------------------------------------------------------------------- + +FROM scratch + +COPY --from=test /test/actual_sample.wav ./ diff --git a/tests/Dockerfile.test.debian.dockerignore b/tests/Dockerfile.test.debian.dockerignore new file mode 100644 index 0000000..6968011 --- /dev/null +++ b/tests/Dockerfile.test.debian.dockerignore @@ -0,0 +1,5 @@ +* +!dist/*.deb +!mimic3-tts/mimic3_tts/VERSION +!tests/apope_sample.wav +!tests/apope_sample.txt diff --git a/tests/Dockerfile.test.docker b/tests/Dockerfile.test.docker new file mode 100644 index 0000000..56182c0 --- /dev/null +++ b/tests/Dockerfile.test.docker @@ -0,0 +1,59 @@ +# Copyright 2022 Mycroft AI Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +# ----------------------------------------------------------------------------- +# Dockerfile for Mimic 3 (https://github.com/MycroftAI/mimic3) +# +# Tests installation and functionality of Mimic 3 Docker image. +# +# Requires Docker buildx: https://docs.docker.com/buildx/working-with-buildx/ +# ----------------------------------------------------------------------------- +FROM mycroftai/mimic3 + +ARG TARGETARCH +ARG TARGETVARIANT + +ENV LANG C.UTF-8 + +WORKDIR /test + +COPY mimic3-tts/mimic3_tts/VERSION ./ + +# Install mimic3 for current architecture +RUN --mount=type=cache,id=apt-run,target=/var/cache/apt \ + export mimic3_version="$(cat VERSION)" && \ + dpkg-architecture | \ + grep 'DEB_HOST_ARCH=' | \ + sed -e 's/.\+=//' | \ + xargs printf "./mimic3-tts_${mimic3_version}_%s.deb" | \ + xargs apt install --yes + +# Version check +RUN export expected_version="$(cat VERSION)" && \ + export actual_version="$(mimic3 --version)" && \ + if [ ! "${expected_version}" = "${actual_version}"]; then \ + echo "${actual_version} != ${expected_version}"; \ + exit 1; \ + fi + +# Generate sample and check +COPY tests/apope_sample.* ./ +RUN mimic3 \ + --deterministic \ + --voice 'en_UK/apope_low' \ + < apope_sample.txt \ + > actual_sample.wav + +RUN diff apope_sample.wav actual_sample.wav diff --git a/tests/Dockerfile.test.docker.dockerignore b/tests/Dockerfile.test.docker.dockerignore new file mode 100644 index 0000000..84962cd --- /dev/null +++ b/tests/Dockerfile.test.docker.dockerignore @@ -0,0 +1,4 @@ +* +!mimic3-tts/mimic3_tts/VERSION +!tests/apope_sample.wav +!tests/apope_sample.txt diff --git a/tests/apope_sample.txt b/tests/apope_sample.txt new file mode 100644 index 0000000..b0a2cf8 --- /dev/null +++ b/tests/apope_sample.txt @@ -0,0 +1 @@ +A rainbow is a meteorological phenomenon that is caused by reflection, refraction and dispersion of light in water droplets resulting in a spectrum of light appearing in the sky. diff --git a/tests/get_sample_hashes.py b/tests/get_sample_hashes.py index de1cb98..0866a29 100644 --- a/tests/get_sample_hashes.py +++ b/tests/get_sample_hashes.py @@ -64,6 +64,11 @@ _TEST_SENTENCES = { "nl": """Een regenboog is een gekleurde cirkelboog die aan de hemel waargenomen kan worden als de, laagstaande, zon tegen een nevel van waterdruppeltjes aan schijnt en de zon zich achter de waarnemer bevindt.""", + "pl": """Tęcza, zjawisko optyczne i meteorologiczne, występujące w postaci + charakterystycznego wielobarwnego łuku powstającego w wyniku + rozszczepienia światła widzialnego, zwykle promieniowania słonecznego, + załamującego się i odbijającego wewnątrz licznych kropli wody mających + kształt zbliżony do kulistego.""", "pt": """Um arco-íris, também popularmente denominado arco-da-velha, é um fenômeno óptico e meteorológico que separa a luz do sol em seu espectro contínuo quando o sol brilha sobre gotículas de água suspensas no ar.""", @@ -76,6 +81,9 @@ _TEST_SENTENCES = { "sw": """Upinde wa mvua ni tao la rangi mbalimbali angani ambalo linaweza kuonekana wakati Jua huangaza kupitia matone ya mvua inayoanguka.""", "te": """ఇంద్ర ధనుస్సు దృష్టి విద్యా సంబంధమయిన వాతావరణ శాస్త్ర సంబంధమయిన దృగ్విషయం.""", + "tn": """Batho botlhe ba tsetswe ba gololosegile le go lekalekana ka seriti + le ditshwanelo. Ba abetswe go akanya le maikutlo, mme ba tshwanetse go + direlana ka mowa wa bokaulengwe.""", "uk": """Весе́лка, також ра́йдуга оптичне явище в атмосфері, що являє собою одну, дві чи декілька різнокольорових дуг (або кіл, якщо дивитися з повітря), що спостерігаються на тлі хмари, якщо вона розташована проти