正在显示
7 个修改的文件
包含
329 行增加
和
10 行删除
.github/workflows/apk-tts-engine.yaml
0 → 100644
| 1 | +name: apk-tts-engine | ||
| 2 | + | ||
| 3 | +on: | ||
| 4 | + push: | ||
| 5 | + branches: | ||
| 6 | + - apk-tts | ||
| 7 | + tags: | ||
| 8 | + - '*' | ||
| 9 | + | ||
| 10 | + workflow_dispatch: | ||
| 11 | + | ||
| 12 | +concurrency: | ||
| 13 | + group: apk-tts-engine-${{ github.ref }} | ||
| 14 | + cancel-in-progress: true | ||
| 15 | + | ||
| 16 | +permissions: | ||
| 17 | + contents: write | ||
| 18 | + | ||
| 19 | +jobs: | ||
| 20 | + apk_tts_engine: | ||
| 21 | + if: github.repository_owner == 'csukuangfj' || github.repository_owner == 'k2-fsa' | ||
| 22 | + runs-on: ${{ matrix.os }} | ||
| 23 | + name: apk for tts engine ${{ matrix.index }}/${{ matrix.total }} | ||
| 24 | + strategy: | ||
| 25 | + fail-fast: false | ||
| 26 | + matrix: | ||
| 27 | + os: [ubuntu-latest] | ||
| 28 | + total: ["40"] | ||
| 29 | + index: ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39"] | ||
| 30 | + | ||
| 31 | + steps: | ||
| 32 | + - uses: actions/checkout@v4 | ||
| 33 | + with: | ||
| 34 | + fetch-depth: 0 | ||
| 35 | + | ||
| 36 | + # https://github.com/actions/setup-java | ||
| 37 | + - uses: actions/setup-java@v4 | ||
| 38 | + with: | ||
| 39 | + distribution: 'temurin' # See 'Supported distributions' for available options | ||
| 40 | + java-version: '21' | ||
| 41 | + | ||
| 42 | + - name: ccache | ||
| 43 | + uses: hendrikmuhs/ccache-action@v1.2 | ||
| 44 | + with: | ||
| 45 | + key: ${{ matrix.os }}-android | ||
| 46 | + | ||
| 47 | + - name: Display NDK HOME | ||
| 48 | + shell: bash | ||
| 49 | + run: | | ||
| 50 | + echo "ANDROID_NDK_LATEST_HOME: ${ANDROID_NDK_LATEST_HOME}" | ||
| 51 | + ls -lh ${ANDROID_NDK_LATEST_HOME} | ||
| 52 | + | ||
| 53 | + - name: Install Python dependencies | ||
| 54 | + shell: bash | ||
| 55 | + run: | | ||
| 56 | + python3 -m pip install --upgrade pip jinja2 iso639-lang | ||
| 57 | + | ||
| 58 | + - name: Generate build script | ||
| 59 | + shell: bash | ||
| 60 | + run: | | ||
| 61 | + cd scripts/apk | ||
| 62 | + | ||
| 63 | + total=${{ matrix.total }} | ||
| 64 | + index=${{ matrix.index }} | ||
| 65 | + | ||
| 66 | + ./generate-tts-apk-script.py --total $total --index $index | ||
| 67 | + | ||
| 68 | + chmod +x build-apk-tts-engine.sh | ||
| 69 | + mv -v ./build-apk-tts-engine.sh ../.. | ||
| 70 | + | ||
| 71 | + - name: build APK for TTS engine | ||
| 72 | + shell: bash | ||
| 73 | + run: | | ||
| 74 | + export CMAKE_CXX_COMPILER_LAUNCHER=ccache | ||
| 75 | + export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" | ||
| 76 | + cmake --version | ||
| 77 | + | ||
| 78 | + export ANDROID_NDK=$ANDROID_NDK_LATEST_HOME | ||
| 79 | + ./build-apk-tts-engine.sh | ||
| 80 | + | ||
| 81 | + - name: Display APK for TTS engine | ||
| 82 | + shell: bash | ||
| 83 | + run: | | ||
| 84 | + ls -lh ./apks/ | ||
| 85 | + du -h -d1 . | ||
| 86 | + | ||
| 87 | + - uses: actions/upload-artifact@v3 | ||
| 88 | + if: false | ||
| 89 | + with: | ||
| 90 | + name: tts-engine-apk | ||
| 91 | + path: ./apks/*.apk | ||
| 92 | + | ||
| 93 | + - name: Publish to huggingface | ||
| 94 | + if: true | ||
| 95 | + env: | ||
| 96 | + HF_TOKEN: ${{ secrets.HF_TOKEN }} | ||
| 97 | + uses: nick-fields/retry@v2 | ||
| 98 | + with: | ||
| 99 | + max_attempts: 20 | ||
| 100 | + timeout_seconds: 200 | ||
| 101 | + shell: bash | ||
| 102 | + command: | | ||
| 103 | + git config --global user.email "csukuangfj@gmail.com" | ||
| 104 | + git config --global user.name "Fangjun Kuang" | ||
| 105 | + | ||
| 106 | + rm -rf huggingface | ||
| 107 | + export GIT_LFS_SKIP_SMUDGE=1 | ||
| 108 | + | ||
| 109 | + git clone https://huggingface.co/csukuangfj/sherpa-onnx-apk huggingface | ||
| 110 | + cd huggingface | ||
| 111 | + git fetch | ||
| 112 | + git pull | ||
| 113 | + git merge -m "merge remote" --ff origin main | ||
| 114 | + | ||
| 115 | + mkdir -p tts | ||
| 116 | + cp -v ../apks/*.apk ./tts-engine/ | ||
| 117 | + git status | ||
| 118 | + git lfs track "*.apk" | ||
| 119 | + git add . | ||
| 120 | + git commit -m "add more tts engine apks" | ||
| 121 | + git push https://csukuangfj:$HF_TOKEN@huggingface.co/csukuangfj/sherpa-onnx-apk main |
| @@ -48,7 +48,7 @@ jobs: | @@ -48,7 +48,7 @@ jobs: | ||
| 48 | - name: Install Python dependencies | 48 | - name: Install Python dependencies |
| 49 | shell: bash | 49 | shell: bash |
| 50 | run: | | 50 | run: | |
| 51 | - python3 -m pip install --upgrade pip jinja2 | 51 | + python3 -m pip install --upgrade pip jinja2 iso639-lang |
| 52 | 52 | ||
| 53 | - name: Generate build script | 53 | - name: Generate build script |
| 54 | shell: bash | 54 | shell: bash |
| @@ -12,11 +12,98 @@ class GetSampleText : Activity() { | @@ -12,11 +12,98 @@ class GetSampleText : Activity() { | ||
| 12 | var result = TextToSpeech.LANG_AVAILABLE | 12 | var result = TextToSpeech.LANG_AVAILABLE |
| 13 | var text: String = "" | 13 | var text: String = "" |
| 14 | when(TtsEngine.lang) { | 14 | when(TtsEngine.lang) { |
| 15 | + "ara" -> { | ||
| 16 | + text = "هذا هو محرك تحويل النص إلى كلام باستخدام الجيل القادم من كالدي" | ||
| 17 | + } | ||
| 18 | + "cat" -> { | ||
| 19 | + text = "Aquest és un motor de text a veu que utilitza Kaldi de nova generació" | ||
| 20 | + } | ||
| 21 | + "ces" -> { | ||
| 22 | + text = "Toto je převodník textu na řeč využívající novou generaci kaldi" | ||
| 23 | + } | ||
| 24 | + "dan" -> { | ||
| 25 | + text = "Dette er en tekst til tale-motor, der bruger næste generation af kaldi" | ||
| 26 | + } | ||
| 27 | + "deu" -> { | ||
| 28 | + text = "Dies ist eine Text-to-Speech-Engine, die Kaldi der nächsten Generation verwendet" | ||
| 29 | + } | ||
| 30 | + "ell" -> { | ||
| 31 | + text = "Αυτή είναι μια μηχανή κειμένου σε ομιλία που χρησιμοποιεί kaldi επόμενης γενιάς" | ||
| 32 | + } | ||
| 15 | "eng" -> { | 33 | "eng" -> { |
| 16 | - text = "This is a text-to-speech engine with next generation Kaldi" | 34 | + text = "This is a text-to-speech engine using next generation Kaldi" |
| 35 | + } | ||
| 36 | + "fin" -> { | ||
| 37 | + text = "Tämä on tekstistä puheeksi -moottori, joka käyttää seuraavan sukupolven kaldia" | ||
| 38 | + } | ||
| 39 | + "fra" -> { | ||
| 40 | + text = "Il s'agit d'un moteur de synthèse vocale utilisant Kaldi de nouvelle génération." | ||
| 41 | + } | ||
| 42 | + "hun" -> { | ||
| 43 | + text = "Ez egy szövegfelolvasó motor a következő generációs kaldi használatával" | ||
| 44 | + } | ||
| 45 | + "isl" -> { | ||
| 46 | + text = "Þetta er texta í tal vél sem notar næstu kynslóð kaldi" | ||
| 47 | + } | ||
| 48 | + "ita" -> { | ||
| 49 | + text = "Questo è un motore di sintesi vocale che utilizza kaldi di nuova generazione" | ||
| 50 | + } | ||
| 51 | + "kat" -> { | ||
| 52 | + text = "ეს არის ტექსტიდან მეტყველების ძრავა შემდეგი თაობის კალდის გამოყენებით" | ||
| 53 | + } | ||
| 54 | + "kaz" -> { | ||
| 55 | + text = "Бұл келесі буын kaldi көмегімен мәтіннен сөйлеуге арналған қозғалтқыш" | ||
| 56 | + } | ||
| 57 | + "ltz" -> { | ||
| 58 | + text = "Dëst ass en Text-zu-Speech-Motor mat der nächster Generatioun Kaldi" | ||
| 59 | + } | ||
| 60 | + "nep" -> { | ||
| 61 | + text = "यो अर्को पुस्ता काल्डी प्रयोग गरेर स्पीच इन्जिनको पाठ हो" | ||
| 62 | + } | ||
| 63 | + "nld" -> { | ||
| 64 | + text = "Dit is een tekst-naar-spraak-engine die gebruik maakt van Kaldi van de volgende generatie" | ||
| 65 | + } | ||
| 66 | + "nor" -> { | ||
| 67 | + text = "Dette er en tekst til tale-motor som bruker neste generasjons kaldi" | ||
| 68 | + } | ||
| 69 | + "pol" -> { | ||
| 70 | + text = "Jest to silnik syntezatora mowy wykorzystujący Kaldi nowej generacji" | ||
| 71 | + } | ||
| 72 | + "por" -> { | ||
| 73 | + text = "Este é um mecanismo de conversão de texto em fala usando Kaldi de próxima geração" | ||
| 74 | + } | ||
| 75 | + "ron" -> { | ||
| 76 | + text = "Acesta este un motor text to speech care folosește generația următoare de kadi" | ||
| 77 | + } | ||
| 78 | + "rus" -> { | ||
| 79 | + text = "Это движок преобразования текста в речь, использующий Kaldi следующего поколения." | ||
| 80 | + } | ||
| 81 | + "slk" -> { | ||
| 82 | + text = "Toto je nástroj na prevod textu na reč využívajúci kaldi novej generácie" | ||
| 83 | + } | ||
| 84 | + "spa" -> { | ||
| 85 | + text = "Este es un motor de texto a voz que utiliza kaldi de próxima generación." | ||
| 86 | + } | ||
| 87 | + "srp" -> { | ||
| 88 | + text = "Ово је механизам за претварање текста у говор који користи калди следеће генерације" | ||
| 89 | + } | ||
| 90 | + "swa" -> { | ||
| 91 | + text = "Haya ni maandishi kwa injini ya hotuba kwa kutumia kizazi kijacho kaldi" | ||
| 92 | + } | ||
| 93 | + "swe" -> { | ||
| 94 | + text = "Detta är en text till tal-motor som använder nästa generations kaldi" | ||
| 95 | + } | ||
| 96 | + "tur" -> { | ||
| 97 | + text = "Bu, yeni nesil kaldi'yi kullanan bir metinden konuşmaya motorudur" | ||
| 98 | + } | ||
| 99 | + "ukr" -> { | ||
| 100 | + text = "Це механізм перетворення тексту на мовлення, який використовує kaldi нового покоління" | ||
| 101 | + } | ||
| 102 | + "vie" -> { | ||
| 103 | + text = "Đây là công cụ chuyển văn bản thành giọng nói sử dụng kaldi thế hệ tiếp theo" | ||
| 17 | } | 104 | } |
| 18 | "zho", "cmn" -> { | 105 | "zho", "cmn" -> { |
| 19 | - text = "使用新一代 Kaldi 进行语音合成" | 106 | + text = "使用新一代卡尔迪的语音合成引擎" |
| 20 | } | 107 | } |
| 21 | else -> { | 108 | else -> { |
| 22 | result = TextToSpeech.LANG_NOT_SUPPORTED | 109 | result = TextToSpeech.LANG_NOT_SUPPORTED |
scripts/apk/build-apk-tts-engine.sh.in
0 → 100644
| 1 | +#!/usr/bin/env bash | ||
| 2 | +# | ||
| 3 | +# Auto generated! Please DO NOT EDIT! | ||
| 4 | + | ||
| 5 | +# Please set the environment variable ANDROID_NDK | ||
| 6 | +# before running this script | ||
| 7 | + | ||
| 8 | +# Inside the $ANDROID_NDK directory, you can find a binary ndk-build | ||
| 9 | +# and some other files like the file "build/cmake/android.toolchain.cmake" | ||
| 10 | + | ||
| 11 | +set -ex | ||
| 12 | + | ||
| 13 | +log() { | ||
| 14 | + # This function is from espnet | ||
| 15 | + local fname=${BASH_SOURCE[1]##*/} | ||
| 16 | + echo -e "$(date '+%Y-%m-%d %H:%M:%S') (${fname}:${BASH_LINENO[0]}:${FUNCNAME[1]}) $*" | ||
| 17 | +} | ||
| 18 | + | ||
| 19 | +SHERPA_ONNX_VERSION=$(grep "SHERPA_ONNX_VERSION" ./CMakeLists.txt | cut -d " " -f 2 | cut -d '"' -f 2) | ||
| 20 | + | ||
| 21 | +log "Building TTS engine APK for sherpa-onnx v${SHERPA_ONNX_VERSION}" | ||
| 22 | + | ||
| 23 | +log "====================arm64-v8a=================" | ||
| 24 | +./build-android-arm64-v8a.sh | ||
| 25 | +log "====================armv7-eabi================" | ||
| 26 | +./build-android-armv7-eabi.sh | ||
| 27 | +log "====================x86-64====================" | ||
| 28 | +./build-android-x86-64.sh | ||
| 29 | +log "====================x86====================" | ||
| 30 | +./build-android-x86.sh | ||
| 31 | + | ||
| 32 | +mkdir -p apks | ||
| 33 | + | ||
| 34 | +{% for tts_model in tts_model_list %} | ||
| 35 | +pushd ./android/SherpaOnnxTtsEngine/app/src/main/assets/ | ||
| 36 | +model_dir={{ tts_model.model_dir }} | ||
| 37 | +model_name={{ tts_model.model_name }} | ||
| 38 | +lang={{ tts_model.lang }} | ||
| 39 | +lang_iso_639_3={{ tts_model.lang_iso_639_3 }} | ||
| 40 | + | ||
| 41 | +wget -qq https://github.com/k2-fsa/sherpa-onnx/releases/download/tts-models/$model_dir.tar.bz2 | ||
| 42 | +tar xf $model_dir.tar.bz2 | ||
| 43 | +rm $model_dir.tar.bz2 | ||
| 44 | + | ||
| 45 | +popd | ||
| 46 | +# Now we are at the project root directory | ||
| 47 | + | ||
| 48 | +git checkout . | ||
| 49 | +pushd android/SherpaOnnxTtsEngine/app/src/main/java/com/k2fsa/sherpa/onnx/tts/engine | ||
| 50 | +sed -i.bak s/"modelDir = null"/"modelDir = \"$model_dir\""/ ./TtsEngine.kt | ||
| 51 | +sed -i.bak s/"modelName = null"/"modelName = \"$model_name\""/ ./TtsEngine.kt | ||
| 52 | +sed -i.bak s/"lang = null"/"lang = \"$lang_iso_639_3\""/ ./TtsEngine.kt | ||
| 53 | + | ||
| 54 | +{% if tts_model.rule_fsts %} | ||
| 55 | + rule_fsts={{ tts_model.rule_fsts }} | ||
| 56 | + sed -i.bak s%"ruleFsts = null"%"ruleFsts = \"$rule_fsts\""% ./TtsEngine.kt | ||
| 57 | +{% endif %} | ||
| 58 | + | ||
| 59 | +{% if tts_model.data_dir %} | ||
| 60 | + data_dir={{ tts_model.data_dir }} | ||
| 61 | + sed -i.bak s%"dataDir = null"%"dataDir = \"$data_dir\""% ./TtsEngine.kt | ||
| 62 | +{% else %} | ||
| 63 | + sed -i.bak s/"lexicon = null"/"lexicon = \"lexicon.txt\""/ ./TtsEngine.kt | ||
| 64 | +{% endif %} | ||
| 65 | + | ||
| 66 | +git diff | ||
| 67 | +popd | ||
| 68 | + | ||
| 69 | +for arch in arm64-v8a armeabi-v7a x86_64 x86; do | ||
| 70 | + log "------------------------------------------------------------" | ||
| 71 | + log "build tts apk for $arch" | ||
| 72 | + log "------------------------------------------------------------" | ||
| 73 | + src_arch=$arch | ||
| 74 | + if [ $arch == "armeabi-v7a" ]; then | ||
| 75 | + src_arch=armv7-eabi | ||
| 76 | + elif [ $arch == "x86_64" ]; then | ||
| 77 | + src_arch=x86-64 | ||
| 78 | + fi | ||
| 79 | + | ||
| 80 | + ls -lh ./build-android-$src_arch/install/lib/*.so | ||
| 81 | + | ||
| 82 | + cp -v ./build-android-$src_arch/install/lib/*.so ./android/SherpaOnnxTtsEngine/app/src/main/jniLibs/$arch/ | ||
| 83 | + | ||
| 84 | + pushd ./android/SherpaOnnxTtsEngine | ||
| 85 | + ./gradlew build | ||
| 86 | + popd | ||
| 87 | + | ||
| 88 | + mv android/SherpaOnnxTtsEngine/app/build/outputs/apk/debug/app-debug.apk ./apks/sherpa-onnx-${SHERPA_ONNX_VERSION}-$arch-$lang-tts-engine-$model_dir.apk | ||
| 89 | + ls -lh apks | ||
| 90 | + rm -v ./android/SherpaOnnxTtsEngine/app/src/main/jniLibs/$arch/*.so | ||
| 91 | +done | ||
| 92 | + | ||
| 93 | +rm -rf ./android/SherpaOnnxTtsEngine/app/src/main/assets/$model_dir | ||
| 94 | +{% endfor %} | ||
| 95 | + | ||
| 96 | +git checkout . | ||
| 97 | + | ||
| 98 | +ls -lh apks/ |
| @@ -18,7 +18,7 @@ log() { | @@ -18,7 +18,7 @@ log() { | ||
| 18 | 18 | ||
| 19 | SHERPA_ONNX_VERSION=$(grep "SHERPA_ONNX_VERSION" ./CMakeLists.txt | cut -d " " -f 2 | cut -d '"' -f 2) | 19 | SHERPA_ONNX_VERSION=$(grep "SHERPA_ONNX_VERSION" ./CMakeLists.txt | cut -d " " -f 2 | cut -d '"' -f 2) |
| 20 | 20 | ||
| 21 | -log "Building APK for sherpa-onnx v${SHERPA_ONNX_VERSION}" | 21 | +log "Building TTS APK for sherpa-onnx v${SHERPA_ONNX_VERSION}" |
| 22 | 22 | ||
| 23 | log "====================arm64-v8a=================" | 23 | log "====================arm64-v8a=================" |
| 24 | ./build-android-arm64-v8a.sh | 24 | ./build-android-arm64-v8a.sh |
| @@ -6,6 +6,9 @@ from typing import List, Optional | @@ -6,6 +6,9 @@ from typing import List, Optional | ||
| 6 | 6 | ||
| 7 | import jinja2 | 7 | import jinja2 |
| 8 | 8 | ||
| 9 | +# pip install iso639-lang | ||
| 10 | +from iso639 import Lang | ||
| 11 | + | ||
| 9 | 12 | ||
| 10 | def get_args(): | 13 | def get_args(): |
| 11 | parser = argparse.ArgumentParser() | 14 | parser = argparse.ArgumentParser() |
| @@ -31,6 +34,12 @@ class TtsModel: | @@ -31,6 +34,12 @@ class TtsModel: | ||
| 31 | lang: str = "" # en, zh, fr, de, etc. | 34 | lang: str = "" # en, zh, fr, de, etc. |
| 32 | rule_fsts: Optional[List[str]] = None | 35 | rule_fsts: Optional[List[str]] = None |
| 33 | data_dir: Optional[str] = None | 36 | data_dir: Optional[str] = None |
| 37 | + lang_iso_639_3: str = "" | ||
| 38 | + | ||
| 39 | + | ||
| 40 | +def convert_lang_to_iso_639_3(models: List[TtsModel]): | ||
| 41 | + for m in models: | ||
| 42 | + m.lang_iso_639_3 = Lang(m.lang).pt3 | ||
| 34 | 43 | ||
| 35 | 44 | ||
| 36 | def get_coqui_models() -> List[TtsModel]: | 45 | def get_coqui_models() -> List[TtsModel]: |
| @@ -234,15 +243,12 @@ def main(): | @@ -234,15 +243,12 @@ def main(): | ||
| 234 | index = args.index | 243 | index = args.index |
| 235 | total = args.total | 244 | total = args.total |
| 236 | assert 0 <= index < total, (index, total) | 245 | assert 0 <= index < total, (index, total) |
| 237 | - environment = jinja2.Environment() | ||
| 238 | - with open("./build-apk-tts.sh.in") as f: | ||
| 239 | - s = f.read() | ||
| 240 | - template = environment.from_string(s) | ||
| 241 | d = dict() | 246 | d = dict() |
| 242 | 247 | ||
| 243 | all_model_list = get_vits_models() | 248 | all_model_list = get_vits_models() |
| 244 | all_model_list += get_piper_models() | 249 | all_model_list += get_piper_models() |
| 245 | all_model_list += get_coqui_models() | 250 | all_model_list += get_coqui_models() |
| 251 | + convert_lang_to_iso_639_3(all_model_list) | ||
| 246 | 252 | ||
| 247 | num_models = len(all_model_list) | 253 | num_models = len(all_model_list) |
| 248 | 254 | ||
| @@ -262,8 +268,15 @@ def main(): | @@ -262,8 +268,15 @@ def main(): | ||
| 262 | d["tts_model_list"].append(all_model_list[s]) | 268 | d["tts_model_list"].append(all_model_list[s]) |
| 263 | print(f"{s}/{num_models}") | 269 | print(f"{s}/{num_models}") |
| 264 | 270 | ||
| 271 | + filename_list = ["./build-apk-tts.sh", "./build-apk-tts-engine.sh"] | ||
| 272 | + for filename in filename_list: | ||
| 273 | + environment = jinja2.Environment() | ||
| 274 | + with open(f"{filename}.in") as f: | ||
| 275 | + s = f.read() | ||
| 276 | + template = environment.from_string(s) | ||
| 277 | + | ||
| 265 | s = template.render(**d) | 278 | s = template.render(**d) |
| 266 | - with open("./build-apk-tts.sh", "w") as f: | 279 | + with open(filename, "w") as f: |
| 267 | print(s, file=f) | 280 | print(s, file=f) |
| 268 | 281 | ||
| 269 | 282 |
-
请 注册 或 登录 后发表评论