Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7c7cb72c13 | ||
|
|
3a105ce922 | ||
|
|
690018c4ab | ||
|
|
6808439ca1 | ||
|
|
8cf56faad2 | ||
|
|
cb7d486288 | ||
|
|
086999fc1b | ||
|
|
a1b889108f | ||
|
|
9f18b24465 | ||
|
|
a3f157249c | ||
|
|
eb08d31509 | ||
|
|
1e1b7fdd8c | ||
|
|
5aad7bcc45 | ||
|
|
dd52597f49 | ||
|
|
5f836e08b8 | ||
|
|
b89b6cdc1d | ||
|
|
558aed1888 | ||
|
|
5eab3d28df | ||
|
|
fd76f496a0 | ||
|
|
4d9b44d9a0 | ||
|
|
951df5a239 | ||
|
|
0a35ee2310 | ||
|
|
efeb2e67e0 | ||
|
|
131f14de76 | ||
|
|
4e67931fe9 | ||
|
|
785525327d | ||
|
|
d4647573cd | ||
|
|
c3895b602c | ||
|
|
f18eb9a4a0 | ||
|
|
2834778e8f | ||
|
|
2f42c69d25 | ||
|
|
8c65f026e6 | ||
|
|
fff01107c8 | ||
|
|
0bdc66f6e5 | ||
|
|
1c3fc86085 | ||
|
|
d9eb0876a6 | ||
|
|
9b4130a8eb | ||
|
|
8fb5b4f695 | ||
|
|
65e306a198 | ||
|
|
3dabb63656 | ||
|
|
241fa91473 | ||
|
|
2a5c8dd58a | ||
|
|
2bfa10d7be | ||
|
|
3501e2e2f3 | ||
|
|
679e3a0982 | ||
|
|
35d05c7689 | ||
|
|
084cc2d2a2 | ||
|
|
a96c82ff01 | ||
|
|
aa7ff1940a | ||
|
|
58465ae14e | ||
|
|
2f49f61645 | ||
|
|
58a70caebc | ||
|
|
d0d470db0f | ||
|
|
068fc72346 | ||
|
|
fc5c8c748f | ||
|
|
24f86d08b7 | ||
|
|
99e402664c | ||
|
|
24cf9eae59 | ||
|
|
18b1582d2a | ||
|
|
96d9df9438 | ||
|
|
4ca156a032 | ||
|
|
5aecb5b7fd | ||
|
|
63c308ff05 | ||
|
|
e6e4b0b47f | ||
|
|
af4c63f1ee | ||
|
|
bedc8148ad | ||
|
|
21cd171719 | ||
|
|
856c0c1baa | ||
|
|
09977956f5 | ||
|
|
2c7feb31e5 | ||
|
|
cead53a808 | ||
|
|
e7996ebc7a | ||
|
|
6815ba0f2e | ||
|
|
51fa4ce9e9 | ||
|
|
043648e24a | ||
|
|
b76ff028f8 | ||
|
|
14214cc141 | ||
|
|
872638a198 | ||
|
|
5d2720c118 | ||
|
|
460216819a | ||
|
|
412d1442a6 | ||
|
|
5a1dd31ab6 | ||
|
|
ce84f153ca | ||
|
|
ab3570c899 | ||
|
|
42f08cd19c | ||
|
|
21fb1b58d9 | ||
|
|
d4741edf94 | ||
|
|
e3c7144272 | ||
|
|
27a4fe2338 | ||
|
|
a0913db3c9 | ||
|
|
645c0d3a67 | ||
|
|
e3878b595b | ||
|
|
825e4a7d12 | ||
|
|
6c20f45154 | ||
|
|
97cda27c7e | ||
|
|
a075495a0a | ||
|
|
b205657be3 | ||
|
|
483d6c8e79 | ||
|
|
9bd4665e6b | ||
|
|
62e1ab7e89 | ||
|
|
740c54db1c | ||
|
|
e188467730 | ||
|
|
743f23240e | ||
|
|
66dadbca25 | ||
|
|
8125b46dbe | ||
|
|
d4bd46f203 | ||
|
|
f13d6d336b | ||
|
|
1fa2f2e110 | ||
|
|
9ad4005e52 | ||
|
|
6d6b92d4b2 | ||
|
|
bf5d913cae | ||
|
|
f52ccd3931 | ||
|
|
37e7c8002d | ||
|
|
ad7382ee68 | ||
|
|
2428bfe357 | ||
|
|
74f3acc51f | ||
|
|
90a98f140b | ||
|
|
885311ecd8 | ||
|
|
c2952e9758 | ||
|
|
7e6e18c6d9 | ||
|
|
47eafafeda | ||
|
|
5edaab1356 | ||
|
|
7bde34d2ce | ||
|
|
0aa4638f68 | ||
|
|
22dd9c741c | ||
|
|
e000b8bb87 | ||
|
|
2d26f309df | ||
|
|
22d3e53a28 | ||
|
|
0ea646dbf3 | ||
|
|
282e3ce84c | ||
|
|
772afd47a1 | ||
|
|
1612835c5d | ||
|
|
ea551d3a84 | ||
|
|
47001203cd | ||
|
|
27ff5a12b0 | ||
|
|
0a89407e4d | ||
|
|
a579c5e6d2 | ||
|
|
5a21d14672 | ||
|
|
f4f5f82bb0 | ||
|
|
7b03804f9e | ||
|
|
f46493e6d8 | ||
|
|
2a64f6ad2b | ||
|
|
3368f8b016 | ||
|
|
121585ae84 | ||
|
|
3e6c11740d | ||
|
|
6b111494b3 | ||
|
|
b376a27da2 | ||
|
|
eeec4de703 | ||
|
|
49f98033b3 | ||
|
|
c1470930f4 | ||
|
|
1dec4f027b | ||
|
|
a9ef8edcb4 | ||
|
|
299238be7d | ||
|
|
29c7ea1526 | ||
|
|
e974e14a10 | ||
|
|
59c654bacd | ||
|
|
969b4e3f46 | ||
|
|
86c64fc9ba | ||
|
|
b8c0db6f56 | ||
|
|
57982cb810 | ||
|
|
6387007f56 | ||
|
|
cdf8d695e2 | ||
|
|
833bf3da4f | ||
|
|
f68086db0b | ||
|
|
1f7842ef5a | ||
|
|
9bb0d1fa58 | ||
|
|
015b9033ec | ||
|
|
7f261bb5e9 | ||
|
|
00b93cfe1b | ||
|
|
c0d01ee931 | ||
|
|
d0ceb2bb65 | ||
|
|
3231e61d56 | ||
|
|
32f3b721c2 | ||
|
|
8c588939d2 | ||
|
|
ff1077f282 | ||
|
|
36d0e92ed9 | ||
|
|
8dfb84d7e2 | ||
|
|
4caecdc5eb | ||
|
|
40f2fbf54e | ||
|
|
ab37dd8849 | ||
|
|
03b02e0e4c | ||
|
|
351f46c7b5 | ||
|
|
71ba584e7c | ||
|
|
b3f53e93cc | ||
|
|
0ed3cb75b5 | ||
|
|
c29de18ad4 | ||
|
|
ec1d0e8c5d | ||
|
|
12bf008b3f | ||
|
|
ecdc10ece5 | ||
|
|
360f70cb0a | ||
|
|
51c91c3d70 | ||
|
|
81a9f4c847 | ||
|
|
cdce7511dc | ||
|
|
6d4b6d336b | ||
|
|
6c4a9b19c7 | ||
|
|
82ecf3eecc | ||
|
|
d750959f52 | ||
|
|
bd74de53da | ||
|
|
fcec9d8f5b | ||
|
|
85e5e6ab86 | ||
|
|
d15931bdda | ||
|
|
abc9cf1fb7 | ||
|
|
2b60f5b0da | ||
|
|
e524063ec2 | ||
|
|
d93906a75f | ||
|
|
ad57deed20 | ||
|
|
d0866e3c6c | ||
|
|
af907a299d | ||
|
|
7928af1bb7 | ||
|
|
4d837a0219 | ||
|
|
e50817a234 | ||
|
|
c3bb58d2af | ||
|
|
c17959f142 | ||
|
|
def2d51c5f | ||
|
|
6166d4f751 | ||
|
|
cd164ae258 | ||
|
|
f089e3e85b | ||
|
|
d008c7ab0a | ||
|
|
a199adfbd6 | ||
|
|
61998b4d39 | ||
|
|
55799b2de8 | ||
|
|
ece55ffe06 | ||
|
|
dbc2582fa6 | ||
|
|
535c9b652a | ||
|
|
6c28d58b4a | ||
|
|
c9a222932c | ||
|
|
7010369966 | ||
|
|
525a337835 | ||
|
|
2bd1ef843e | ||
|
|
a9d95fc563 | ||
|
|
1a37ae4ba5 | ||
|
|
8c6fc4853d | ||
|
|
f34ebbd675 | ||
|
|
64cffcdf80 | ||
|
|
2731a559f4 | ||
|
|
a91a83268f | ||
|
|
5d406fbbfb | ||
|
|
cefd1e045b | ||
|
|
bec4e905d3 | ||
|
|
f5e99a5e72 | ||
|
|
631ea6dd8a | ||
|
|
08a04ba506 | ||
|
|
c78927b80a | ||
|
|
04e08c58b8 | ||
|
|
893747c9a9 | ||
|
|
d52dcf86d5 | ||
|
|
ad0eab1224 | ||
|
|
62d1cc05d3 | ||
|
|
b8292da92f | ||
|
|
180adb45dd | ||
|
|
5c0f08d49e | ||
|
|
571872dbe2 | ||
|
|
467bfbea55 | ||
|
|
5a3cbb6366 | ||
|
|
2351e418fd | ||
|
|
b987ff38a7 | ||
|
|
43899028e3 | ||
|
|
2c1ca8b2a3 | ||
|
|
139162c4e6 | ||
|
|
7da78ec045 | ||
|
|
11c70c7432 | ||
|
|
c2822edb1b | ||
|
|
cba7ed7b88 | ||
|
|
471a26f2a4 | ||
|
|
34d1b81ae4 | ||
|
|
f1b4d4b8b6 | ||
|
|
c05237143b | ||
|
|
c5846b832a | ||
|
|
7a38730c56 | ||
|
|
0b1e6f8711 | ||
|
|
8c38e925dd | ||
|
|
df70481934 | ||
|
|
e43c58a56e | ||
|
|
8dc9304a4c | ||
|
|
102424669b | ||
|
|
5210d075c1 | ||
|
|
30db974439 | ||
|
|
c2a558110b | ||
|
|
83ac18b83f | ||
|
|
6e36415746 | ||
|
|
fe7ffb535c | ||
|
|
80b7fccb50 | ||
|
|
2790ee9860 | ||
|
|
74ce2584cc | ||
|
|
8dd11541b4 | ||
|
|
d1317b49f0 | ||
|
|
a50d5a5028 | ||
|
|
33264554cd | ||
|
|
4a116e359a | ||
|
|
36bfb17eda | ||
|
|
697fb098c3 | ||
|
|
51a8e93df7 | ||
|
|
257fa59e70 | ||
|
|
7dbad85fc3 | ||
|
|
510894c793 | ||
|
|
a85058a3ac | ||
|
|
e54c7e4362 | ||
|
|
1f2ad303a0 | ||
|
|
d4a04096c8 | ||
|
|
dd45008e88 | ||
|
|
e9d9f54de6 | ||
|
|
3230397a82 | ||
|
|
840889ac9a | ||
|
|
d3e061b127 | ||
|
|
a428f67a2e | ||
|
|
b223e7b247 | ||
|
|
9296843508 | ||
|
|
f0c9e3e6bb | ||
|
|
22de1bf0c6 | ||
|
|
621f5434a7 | ||
|
|
81c8354cf8 | ||
|
|
3bc55a91e5 | ||
|
|
fc857f464c | ||
|
|
50aa6de96c | ||
|
|
10299194f8 | ||
|
|
d80d1ace3c | ||
|
|
f19f4e9a29 | ||
|
|
7e4ceef0e8 | ||
|
|
c1bc1f26cd | ||
|
|
70d385133d | ||
|
|
13b2eb5fe3 | ||
|
|
ff4b9d9e99 | ||
|
|
a22830f700 | ||
|
|
374c794fa9 | ||
|
|
d2adbd9c1e | ||
|
|
1dc4b8bf50 | ||
|
|
0eba72fc47 | ||
|
|
f2c87dcdab | ||
|
|
4a727ce14a | ||
|
|
6e15d43e63 | ||
|
|
dedc13b3b6 | ||
|
|
7cb206e531 | ||
|
|
4f80b39cd0 | ||
|
|
d5fa6bb46d | ||
|
|
332582baea | ||
|
|
2bd7ebc514 | ||
|
|
e5acc8bdbd | ||
|
|
7718bfd3ea | ||
|
|
002c5ad9db | ||
|
|
2c14847708 | ||
|
|
3647d69007 | ||
|
|
56a7ea1d8f | ||
|
|
863a7cd841 | ||
|
|
2e1709ab58 | ||
|
|
9c4efdc135 | ||
|
|
28675c976c | ||
|
|
afe3b9fe0b | ||
|
|
2e4d52170d | ||
|
|
0e2cc25571 | ||
|
|
abaa56e8f4 | ||
|
|
d0dc9f3212 | ||
|
|
67dcc411ad | ||
|
|
b11a087dc8 | ||
|
|
e068115eef | ||
|
|
0ec580539a | ||
|
|
e9feae12ad | ||
|
|
e183e3a7bb | ||
|
|
8a2b669da9 | ||
|
|
67d2b1c5ea | ||
|
|
f3b44424ef | ||
|
|
3b5c4b9b68 | ||
|
|
e452a926f2 | ||
|
|
b65291d44d | ||
|
|
b28ecaf43e | ||
|
|
ba1328311c | ||
|
|
9e6b9396bc | ||
|
|
2e40db5fe5 | ||
|
|
720bf8697f | ||
|
|
1893d1a130 | ||
|
|
8472baf031 | ||
|
|
6cab618706 | ||
|
|
ebf3b362f7 | ||
|
|
2dd303f53c | ||
|
|
df69fb0b07 | ||
|
|
a0d9771fa6 | ||
|
|
a71c46bb98 | ||
|
|
995f317b4f | ||
|
|
6ef2de2923 | ||
|
|
37c4e86566 | ||
|
|
11071b279b | ||
|
|
5ab7463f35 | ||
|
|
74c9238e3a | ||
|
|
e874e46304 | ||
|
|
b32df6ac15 | ||
|
|
b76dd3561f | ||
|
|
60bfbdcabd | ||
|
|
c128d0851b | ||
|
|
2f3b7762e4 | ||
|
|
0e594f5098 | ||
|
|
14151d4dda | ||
|
|
94ab21fb15 | ||
|
|
1acac3d6c6 | ||
|
|
95ec2dc9d2 | ||
|
|
6b93eb6c1e | ||
|
|
838578a042 | ||
|
|
2f689f0438 | ||
|
|
022025ded6 | ||
|
|
320a7a6aba | ||
|
|
fa82870883 | ||
|
|
a094d4f9da | ||
|
|
bb028af694 | ||
|
|
aeb225ec7c | ||
|
|
06a632459e | ||
|
|
221efbddb4 | ||
|
|
e81a88938a | ||
|
|
65e257077c | ||
|
|
95659d5b7a | ||
|
|
ff57270286 | ||
|
|
4fc61ba99a | ||
|
|
3cd22081f4 | ||
|
|
d20ee95e67 | ||
|
|
cd47f6b123 | ||
|
|
53a2d0a65e |
No files matched your search
@@ -0,0 +1 @@
|
||||
ko_fi: erew123
|
||||
@@ -1,13 +1,14 @@
|
||||
---
|
||||
name: Bug report/Support request
|
||||
about: Create a report to help us improve
|
||||
name: Support Request/Issue
|
||||
about: Use this to create a support request or report a bug/issue
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
🔴 If you have installed AllTalk in a custom Python environment, I will only be able to provide limited assistance/support. AllTalk draws on a variety of scripts and libraries that are not written or managed by myself, and they may fail, error or give strange results in custom built python environments.
|
||||
|
||||
Please generate a diagnostics report and upload the "diagnostics.log".
|
||||
🔴 Please generate a diagnostics report and upload the "diagnostics.log" as this helps me understand your configuration.
|
||||
|
||||
https://github.com/erew123/alltalk_tts/tree/main?#-how-to-make-a-diagnostics-report-file
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
about: Use this to create a Feature request
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
name: Publish Docker image
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
release:
|
||||
types: [published]
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build_and_push:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- dockerfile: "Dockerfile"
|
||||
platforms: "linux/amd64"
|
||||
tag_name: "cpu"
|
||||
- dockerfile: "nvidia.Dockerfile"
|
||||
platforms: "linux/amd64"
|
||||
tag_name: "cuda"
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Lowercase Actor and Extract Repo Name
|
||||
run: |
|
||||
echo "ACTOR_LOWER=$(echo ${{ github.actor }} | tr '[:upper:]' '[:lower:]')" >> $GITHUB_ENV
|
||||
echo "REPO_NAME=$(echo ${{ github.repository }} | cut -d'/' -f 2)" >> $GITHUB_ENV
|
||||
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ env.ACTOR_LOWER }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Login to DockerHub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ vars.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: Build and push Docker image
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
file: ./${{ matrix.dockerfile }}
|
||||
platforms: ${{ matrix.platforms }}
|
||||
push: true
|
||||
tags: |
|
||||
ghcr.io/${{ env.ACTOR_LOWER }}/${{ env.REPO_NAME }}:${{ matrix.tag_name }}-${{ github.sha }}
|
||||
ghcr.io/${{ env.ACTOR_LOWER }}/${{ env.REPO_NAME }}:${{ matrix.tag_name }}
|
||||
ghcr.io/${{ env.ACTOR_LOWER }}/${{ env.REPO_NAME }}:latest
|
||||
${{ vars.DOCKERHUB_USERNAME }}/${{ env.REPO_NAME }}:${{ matrix.tag_name }}-${{ github.sha }}
|
||||
${{ vars.DOCKERHUB_USERNAME }}/${{ env.REPO_NAME }}:${{ matrix.tag_name }}
|
||||
${{ vars.DOCKERHUB_USERNAME }}/${{ env.REPO_NAME }}:latest
|
||||
|
||||
- name: Docker Hub Description
|
||||
uses: peter-evans/dockerhub-description@v3.4.2
|
||||
with:
|
||||
username: ${{ vars.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
repository: ${{ vars.DOCKERHUB_USERNAME }}/${{ env.REPO_NAME }}
|
||||
@@ -1,6 +1,7 @@
|
||||
voices/*.*
|
||||
models/*.*
|
||||
outputs/*.*
|
||||
finetune/*.*
|
||||
config.json
|
||||
confignew.json
|
||||
models.json
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"files.associations": {
|
||||
"*.html": "jinja-html"
|
||||
},
|
||||
"emmet.includeLanguages": {
|
||||
"jinja-html": "html",
|
||||
"jinja2": "html"
|
||||
},
|
||||
}
|
||||
@@ -1,285 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// DeepSpeed Team
|
||||
|
||||
#include <ATen/cuda/CUDAContext.h>
|
||||
#include <torch/extension.h>
|
||||
#include <cassert>
|
||||
#include <vector>
|
||||
#include "quantization.h"
|
||||
|
||||
template <typename T>
|
||||
at::Tensor ds_quantize(at::Tensor& vals, int groups, int bits)
|
||||
{
|
||||
auto t_size = vals.sizes();
|
||||
int size = 1;
|
||||
for (auto dim : t_size) size *= dim;
|
||||
|
||||
if ((((size / groups) - 1) / 4096 + 1) <= 256) {
|
||||
launch_fake_quantize_kernel(
|
||||
(T*)vals.data_ptr(), size, groups, bits, at::cuda::getCurrentCUDAStream());
|
||||
}
|
||||
return vals;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
at::Tensor ds_sr_quantize(at::Tensor& vals, int groups, int bits)
|
||||
{
|
||||
auto t_size = vals.sizes();
|
||||
int size = 1;
|
||||
for (auto dim : t_size) size *= dim;
|
||||
|
||||
if (((size / groups) / 4 / 1024) <= 256) {
|
||||
launch_sr_fake_quantize_kernel(
|
||||
(T*)vals.data_ptr(), size, groups, bits, at::cuda::getCurrentCUDAStream());
|
||||
}
|
||||
return vals;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
at::Tensor ds_quantize_asym(at::Tensor& vals, int groups, int bits)
|
||||
{
|
||||
auto t_size = vals.sizes();
|
||||
int size = 1;
|
||||
for (auto dim : t_size) size *= dim;
|
||||
|
||||
if ((((size / groups) - 1) / 4096 + 1) <= 256) {
|
||||
launch_fake_quantize_kernel_asym(
|
||||
(T*)vals.data_ptr(), size, groups, bits, at::cuda::getCurrentCUDAStream());
|
||||
}
|
||||
return vals;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
at::Tensor ds_sr_quantize_asym(at::Tensor& vals, int groups, int bits)
|
||||
{
|
||||
auto t_size = vals.sizes();
|
||||
int size = 1;
|
||||
for (auto dim : t_size) size *= dim;
|
||||
|
||||
if (((size / groups) / 4 / 1024) <= 256) {
|
||||
launch_sr_fake_quantize_kernel_asym(
|
||||
(T*)vals.data_ptr(), size, groups, bits, at::cuda::getCurrentCUDAStream());
|
||||
}
|
||||
return vals;
|
||||
}
|
||||
|
||||
std::vector<at::Tensor> quantize_kernel(at::Tensor& input_vals,
|
||||
int groups,
|
||||
int numBits,
|
||||
quantize::Type quantType)
|
||||
{
|
||||
auto dtype = at::kFloat;
|
||||
auto params_options = at::TensorOptions()
|
||||
.dtype(dtype)
|
||||
.layout(at::kStrided)
|
||||
.device(at::kCUDA)
|
||||
.requires_grad(false);
|
||||
const int param_elems = (quantize::requires_offset(quantType)) ? 2 : 1;
|
||||
auto params = torch::empty({groups, param_elems}, params_options);
|
||||
|
||||
auto output_options = at::TensorOptions()
|
||||
.dtype(at::kChar)
|
||||
.layout(at::kStrided)
|
||||
.device(at::kCUDA)
|
||||
.requires_grad(false);
|
||||
|
||||
auto output_sizes = input_vals.sizes().vec();
|
||||
output_sizes[output_sizes.size() - 1] /= numBits == 8 ? 1 : 2;
|
||||
auto output = torch::empty(output_sizes, output_options);
|
||||
|
||||
const int elems_per_group = at::numel(input_vals) / groups;
|
||||
|
||||
launch_quant((int8_t*)output.data_ptr(),
|
||||
(float*)params.data_ptr(),
|
||||
(__half*)input_vals.data_ptr(),
|
||||
groups,
|
||||
elems_per_group,
|
||||
numBits,
|
||||
quantType,
|
||||
at::cuda::getCurrentCUDAStream());
|
||||
|
||||
return {output, params};
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
at::Tensor dequantize(at::Tensor& quantized_data,
|
||||
at::Tensor& params,
|
||||
int groups,
|
||||
int num_bits,
|
||||
quantize::Type quant_type)
|
||||
{
|
||||
auto dtype = (std::is_same<T, float>::value) ? torch::kFloat32 : torch::kFloat16;
|
||||
auto output_options = at::TensorOptions()
|
||||
.dtype(dtype)
|
||||
.layout(at::kStrided)
|
||||
.device(at::kCUDA)
|
||||
.requires_grad(false);
|
||||
|
||||
auto output_sizes = quantized_data.sizes().vec();
|
||||
output_sizes[output_sizes.size() - 1] *= num_bits == 8 ? 1 : 2;
|
||||
auto output = torch::empty(output_sizes, output_options);
|
||||
|
||||
const int total_elems = at::numel(output);
|
||||
const int elems_per_group = total_elems / groups;
|
||||
|
||||
launch_dequantize_kernel((T*)output.data_ptr(),
|
||||
(const int8_t*)quantized_data.data_ptr(),
|
||||
(const float*)params.data_ptr(),
|
||||
quant_type,
|
||||
num_bits,
|
||||
elems_per_group,
|
||||
total_elems,
|
||||
at::cuda::getCurrentCUDAStream());
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
at::Tensor dequantize_int4_to_half_experimental(at::Tensor& data_in,
|
||||
at::Tensor& scale_buffer,
|
||||
at::Tensor& min_val_buffer,
|
||||
int num_group,
|
||||
int group_size)
|
||||
{
|
||||
auto output_options = at::TensorOptions().dtype(at::kHalf).device(at::kCUDA);
|
||||
auto output = torch::empty({num_group, group_size}, output_options);
|
||||
|
||||
launch_dequantize_int4_to_half_experimental((uint8_t*)data_in.data_ptr(),
|
||||
(half*)output.data_ptr(),
|
||||
(half*)scale_buffer.data_ptr(),
|
||||
(half*)min_val_buffer.data_ptr(),
|
||||
num_group,
|
||||
group_size,
|
||||
at::cuda::getCurrentCUDAStream());
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
std::vector<at::Tensor> ds_swizzle_quant(at::Tensor& input_vals,
|
||||
int groups,
|
||||
int num_bits,
|
||||
quantize::Type quant_type,
|
||||
int pipeline_size,
|
||||
int nodes,
|
||||
int devices_per_node)
|
||||
{
|
||||
auto scales_options = at::TensorOptions()
|
||||
.dtype(at::kFloat)
|
||||
.layout(at::kStrided)
|
||||
.device(at::kCUDA)
|
||||
.requires_grad(false);
|
||||
const int scales_elems = (quantize::requires_offset(quant_type)) ? 2 : 1;
|
||||
auto scales = torch::empty({groups, scales_elems}, scales_options);
|
||||
|
||||
auto output_options = at::TensorOptions()
|
||||
.dtype(at::kChar)
|
||||
.layout(at::kStrided)
|
||||
.device(at::kCUDA)
|
||||
.requires_grad(false);
|
||||
|
||||
const int quantization_scalar = 8 / num_bits;
|
||||
const int compressed_vals = at::numel(input_vals) / quantization_scalar;
|
||||
|
||||
auto output = torch::empty({compressed_vals}, output_options);
|
||||
const int elems_per_group = at::numel(input_vals) / groups;
|
||||
|
||||
launch_swizzled_quant((int8_t*)output.data_ptr(),
|
||||
(float*)scales.data_ptr(),
|
||||
(__half*)input_vals.data_ptr(),
|
||||
num_bits,
|
||||
quant_type,
|
||||
groups,
|
||||
elems_per_group,
|
||||
pipeline_size,
|
||||
nodes,
|
||||
devices_per_node,
|
||||
at::cuda::getCurrentCUDAStream());
|
||||
|
||||
return {output, scales};
|
||||
}
|
||||
|
||||
std::vector<at::Tensor> quantized_reduction(at::Tensor& input_vals,
|
||||
at::Tensor& input_scales,
|
||||
int in_groups,
|
||||
int out_groups,
|
||||
int num_bits,
|
||||
quantize::Type quant_type,
|
||||
int devices_per_node)
|
||||
{
|
||||
auto scales_options = at::TensorOptions()
|
||||
.dtype(at::kFloat)
|
||||
.layout(at::kStrided)
|
||||
.device(at::kCUDA)
|
||||
.requires_grad(false);
|
||||
const int scales_elems = (quantize::requires_offset(quant_type)) ? 2 : 1;
|
||||
auto scales = torch::empty({out_groups, scales_elems}, scales_options);
|
||||
|
||||
auto output_options = at::TensorOptions()
|
||||
.dtype(at::kChar)
|
||||
.layout(at::kStrided)
|
||||
.device(at::kCUDA)
|
||||
.requires_grad(false);
|
||||
|
||||
std::vector<int64_t> sz_vector(input_vals.sizes().begin(), input_vals.sizes().end());
|
||||
sz_vector[sz_vector.size() - 1] = sz_vector.back() / devices_per_node; // num of GPU per nodes
|
||||
at::IntArrayRef sz(sz_vector);
|
||||
auto output = torch::empty(sz, output_options);
|
||||
|
||||
const int elems_per_in_tensor = at::numel(input_vals) / devices_per_node;
|
||||
const int elems_per_in_group = elems_per_in_tensor / (in_groups / devices_per_node);
|
||||
const int elems_per_out_group = elems_per_in_tensor / out_groups;
|
||||
|
||||
// old code:
|
||||
// std::vector<long int> sz(input_vals.sizes().begin(), input_vals.sizes().end());
|
||||
// sz[sz.size() - 1] = sz.back() / devices_per_node; // num of GPU per nodes
|
||||
// const int elems_per_in_tensor = at::numel(input_vals) / devices_per_node;
|
||||
// auto output = torch::empty(sz, output_options);
|
||||
|
||||
// const int elems_per_in_group = elems_per_in_tensor / (in_groups / devices_per_node);
|
||||
// const int elems_per_out_group = elems_per_in_tensor / out_groups;
|
||||
|
||||
launch_dequant_reduce((int8_t*)output.data_ptr(),
|
||||
(float*)scales.data_ptr(),
|
||||
(const int8_t*)input_vals.data_ptr(),
|
||||
(const float*)input_scales.data_ptr(),
|
||||
devices_per_node,
|
||||
num_bits,
|
||||
quant_type,
|
||||
out_groups,
|
||||
elems_per_out_group,
|
||||
elems_per_in_tensor,
|
||||
in_groups / devices_per_node,
|
||||
elems_per_in_group,
|
||||
at::cuda::getCurrentCUDAStream());
|
||||
return {output, scales};
|
||||
}
|
||||
|
||||
PYBIND11_MODULE(TORCH_EXTENSION_NAME, m)
|
||||
{
|
||||
m.def("ds_quantize_fp32", &ds_quantize<float>, "DeepSpeed Quantize with fp32 (CUDA)");
|
||||
m.def("ds_quantize_fp16", &ds_quantize<__half>, "DeepSpeed Quantize with fp16 (CUDA)");
|
||||
m.def("ds_sr_quantize_fp32", &ds_sr_quantize<float>, "DeepSpeed Quantize with fp32 (CUDA)");
|
||||
m.def("ds_sr_quantize_fp16", &ds_sr_quantize<__half>, "DeepSpeed Quantize with fp16 (CUDA)");
|
||||
m.def("ds_quantize_asym_fp32", &ds_quantize_asym<float>, "DeepSpeed Quantize with fp32 (CUDA)");
|
||||
m.def(
|
||||
"ds_quantize_asym_fp16", &ds_quantize_asym<__half>, "DeepSpeed Quantize with fp16 (CUDA)");
|
||||
m.def("ds_sr_quantize_asym_fp32",
|
||||
&ds_sr_quantize_asym<float>,
|
||||
"DeepSpeed Quantize with fp32 (CUDA)");
|
||||
m.def("ds_sr_quantize_asym_fp16",
|
||||
&ds_sr_quantize_asym<__half>,
|
||||
"DeepSpeed Quantize with fp16 (CUDA)");
|
||||
pybind11::enum_<quantize::Type>(m, "QuantizationType")
|
||||
.value("Symmetric", quantize::Type::Symmetric)
|
||||
.value("Asymmetric", quantize::Type::Asymmetric)
|
||||
.export_values();
|
||||
m.def("quantize", &quantize_kernel);
|
||||
m.def("dequantize", &dequantize<__half>);
|
||||
m.def("dequantize_fp32", &dequantize<float>);
|
||||
m.def("dequantize_int4_to_half_experimental",
|
||||
&dequantize_int4_to_half_experimental,
|
||||
"Dequantize int4 to half (experimental)");
|
||||
m.def("swizzle_quant", &ds_swizzle_quant);
|
||||
m.def("quantized_reduction", &quantized_reduction);
|
||||
}
|
||||
@@ -1,160 +0,0 @@
|
||||
# Copyright (c) Microsoft Corporation.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
# DeepSpeed Team
|
||||
|
||||
import os
|
||||
import torch
|
||||
import deepspeed
|
||||
import subprocess
|
||||
import argparse
|
||||
import psutil
|
||||
from .ops.op_builder.all_ops import ALL_OPS
|
||||
from .git_version_info import installed_ops, torch_info
|
||||
from deepspeed.accelerator import get_accelerator
|
||||
|
||||
GREEN = '\033[92m'
|
||||
RED = '\033[91m'
|
||||
YELLOW = '\033[93m'
|
||||
END = '\033[0m'
|
||||
SUCCESS = f"{GREEN} [SUCCESS] {END}"
|
||||
OKAY = f"{GREEN}[OKAY]{END}"
|
||||
WARNING = f"{YELLOW}[WARNING]{END}"
|
||||
FAIL = f'{RED}[FAIL]{END}'
|
||||
INFO = '[INFO]'
|
||||
|
||||
color_len = len(GREEN) + len(END)
|
||||
okay = f"{GREEN}[OKAY]{END}"
|
||||
warning = f"{YELLOW}[WARNING]{END}"
|
||||
|
||||
|
||||
def op_report(verbose=True):
|
||||
max_dots = 23
|
||||
max_dots2 = 11
|
||||
h = ["op name", "installed", "compatible"]
|
||||
print("-" * (max_dots + max_dots2 + len(h[0]) + len(h[1])))
|
||||
print("DeepSpeed C++/CUDA extension op report")
|
||||
print("-" * (max_dots + max_dots2 + len(h[0]) + len(h[1])))
|
||||
|
||||
print("NOTE: Ops not installed will be just-in-time (JIT) compiled at\n"
|
||||
" runtime if needed. Op compatibility means that your system\n"
|
||||
" meet the required dependencies to JIT install the op.")
|
||||
|
||||
print("-" * (max_dots + max_dots2 + len(h[0]) + len(h[1])))
|
||||
print("JIT compiled ops requires ninja")
|
||||
ninja_status = OKAY if ninja_installed() else FAIL
|
||||
print('ninja', "." * (max_dots - 5), ninja_status)
|
||||
print("-" * (max_dots + max_dots2 + len(h[0]) + len(h[1])))
|
||||
print(h[0], "." * (max_dots - len(h[0])), h[1], "." * (max_dots2 - len(h[1])), h[2])
|
||||
print("-" * (max_dots + max_dots2 + len(h[0]) + len(h[1])))
|
||||
installed = f"{GREEN}[YES]{END}"
|
||||
no = f"{YELLOW}[NO]{END}"
|
||||
for op_name, builder in ALL_OPS.items():
|
||||
dots = "." * (max_dots - len(op_name))
|
||||
is_compatible = OKAY if builder.is_compatible(verbose) else no
|
||||
is_installed = installed if installed_ops.get(op_name, False) else no
|
||||
dots2 = '.' * ((len(h[1]) + (max_dots2 - len(h[1]))) - (len(is_installed) - color_len))
|
||||
print(op_name, dots, is_installed, dots2, is_compatible)
|
||||
print("-" * (max_dots + max_dots2 + len(h[0]) + len(h[1])))
|
||||
|
||||
|
||||
def ninja_installed():
|
||||
try:
|
||||
import ninja # noqa: F401 # type: ignore
|
||||
except ImportError:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def nvcc_version():
|
||||
import torch.utils.cpp_extension
|
||||
cuda_home = torch.utils.cpp_extension.CUDA_HOME
|
||||
if cuda_home is None:
|
||||
return f"{RED} [FAIL] cannot find CUDA_HOME via torch.utils.cpp_extension.CUDA_HOME={torch.utils.cpp_extension.CUDA_HOME} {END}"
|
||||
try:
|
||||
output = subprocess.check_output([cuda_home + "/bin/nvcc", "-V"], universal_newlines=True)
|
||||
except FileNotFoundError:
|
||||
return f"{RED} [FAIL] nvcc missing {END}"
|
||||
output_split = output.split()
|
||||
release_idx = output_split.index("release")
|
||||
release = output_split[release_idx + 1].replace(',', '').split(".")
|
||||
return ".".join(release)
|
||||
|
||||
|
||||
def get_shm_size():
|
||||
try:
|
||||
temp_dir = os.getenv('TEMP') or os.getenv('TMP') or os.path.join(os.path.expanduser('~'), 'tmp')
|
||||
shm_stats = psutil.disk_usage(temp_dir)
|
||||
shm_size = shm_stats.total
|
||||
shm_hbytes = human_readable_size(shm_size)
|
||||
warn = []
|
||||
if shm_size < 512 * 1024**2:
|
||||
warn.append(
|
||||
f" {YELLOW} [WARNING] Shared memory size might be too small, consider increasing it. {END}"
|
||||
)
|
||||
# Add additional warnings specific to your use case if needed.
|
||||
return shm_hbytes, warn
|
||||
except Exception as e:
|
||||
return "UNKNOWN", [f"Error getting shared memory size: {e}"]
|
||||
|
||||
def human_readable_size(size):
|
||||
units = ['B', 'KB', 'MB', 'GB', 'TB']
|
||||
i = 0
|
||||
while size >= 1024 and i < len(units) - 1:
|
||||
size /= 1024
|
||||
i += 1
|
||||
return f'{size:.2f} {units[i]}'
|
||||
|
||||
|
||||
def debug_report():
|
||||
max_dots = 33
|
||||
|
||||
report = [("torch install path", torch.__path__), ("torch version", torch.__version__),
|
||||
("deepspeed install path", deepspeed.__path__),
|
||||
("deepspeed info", f"{deepspeed.__version__}, {deepspeed.__git_hash__}, {deepspeed.__git_branch__}")]
|
||||
if get_accelerator().device_name() == 'cuda':
|
||||
hip_version = getattr(torch.version, "hip", None)
|
||||
report.extend([("torch cuda version", torch.version.cuda), ("torch hip version", hip_version),
|
||||
("nvcc version", (None if hip_version else nvcc_version())),
|
||||
("deepspeed wheel compiled w.", f"torch {torch_info['version']}, " +
|
||||
(f"hip {torch_info['hip_version']}" if hip_version else f"cuda {torch_info['cuda_version']}"))
|
||||
])
|
||||
else:
|
||||
report.extend([("deepspeed wheel compiled w.", f"torch {torch_info['version']} ")])
|
||||
|
||||
report.append(("shared memory (/dev/shm) size", get_shm_size()))
|
||||
|
||||
print("DeepSpeed general environment info:")
|
||||
for name, value in report:
|
||||
warns = []
|
||||
if isinstance(value, tuple):
|
||||
value, warns = value
|
||||
print(name, "." * (max_dots - len(name)), value)
|
||||
if warns:
|
||||
for warn in warns:
|
||||
print(warn)
|
||||
|
||||
|
||||
def parse_arguments():
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('--hide_operator_status',
|
||||
action='store_true',
|
||||
help='Suppress display of installation and compatibility statuses of DeepSpeed operators. ')
|
||||
parser.add_argument('--hide_errors_and_warnings', action='store_true', help='Suppress warning and error messages.')
|
||||
args = parser.parse_args()
|
||||
return args
|
||||
|
||||
|
||||
def main(hide_operator_status=False, hide_errors_and_warnings=False):
|
||||
if not hide_operator_status:
|
||||
op_report(verbose=not hide_errors_and_warnings)
|
||||
debug_report()
|
||||
|
||||
|
||||
def cli_main():
|
||||
args = parse_arguments()
|
||||
main(hide_operator_status=args.hide_operator_status, hide_errors_and_warnings=args.hide_errors_and_warnings)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -1,299 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// DeepSpeed Team
|
||||
|
||||
#include <ATen/cuda/CUDAContext.h>
|
||||
#include <torch/extension.h>
|
||||
#include <cassert>
|
||||
#include <vector>
|
||||
#include "quantization.h"
|
||||
|
||||
template <typename T>
|
||||
at::Tensor ds_quantize(at::Tensor& vals, int groups, int bits)
|
||||
{
|
||||
auto t_size = vals.sizes();
|
||||
int size = 1;
|
||||
for (auto dim : t_size) size *= dim;
|
||||
|
||||
if ((((size / groups) - 1) / 4096 + 1) <= 256) {
|
||||
launch_fake_quantize_kernel(
|
||||
(T*)vals.data_ptr(), size, groups, bits, at::cuda::getCurrentCUDAStream());
|
||||
}
|
||||
return vals;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
at::Tensor ds_sr_quantize(at::Tensor& vals, int groups, int bits)
|
||||
{
|
||||
auto t_size = vals.sizes();
|
||||
int size = 1;
|
||||
for (auto dim : t_size) size *= dim;
|
||||
|
||||
if (((size / groups) / 4 / 1024) <= 256) {
|
||||
launch_sr_fake_quantize_kernel(
|
||||
(T*)vals.data_ptr(), size, groups, bits, at::cuda::getCurrentCUDAStream());
|
||||
}
|
||||
return vals;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
at::Tensor ds_quantize_asym(at::Tensor& vals, int groups, int bits)
|
||||
{
|
||||
auto t_size = vals.sizes();
|
||||
int size = 1;
|
||||
for (auto dim : t_size) size *= dim;
|
||||
|
||||
if ((((size / groups) - 1) / 4096 + 1) <= 256) {
|
||||
launch_fake_quantize_kernel_asym(
|
||||
(T*)vals.data_ptr(), size, groups, bits, at::cuda::getCurrentCUDAStream());
|
||||
}
|
||||
return vals;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
at::Tensor ds_sr_quantize_asym(at::Tensor& vals, int groups, int bits)
|
||||
{
|
||||
auto t_size = vals.sizes();
|
||||
int size = 1;
|
||||
for (auto dim : t_size) size *= dim;
|
||||
|
||||
if (((size / groups) / 4 / 1024) <= 256) {
|
||||
launch_sr_fake_quantize_kernel_asym(
|
||||
(T*)vals.data_ptr(), size, groups, bits, at::cuda::getCurrentCUDAStream());
|
||||
}
|
||||
return vals;
|
||||
}
|
||||
|
||||
std::vector<at::Tensor> quantize_kernel(at::Tensor& input_vals,
|
||||
int groups,
|
||||
int numBits,
|
||||
quantize::Type quantType)
|
||||
{
|
||||
auto dtype = at::kFloat;
|
||||
auto params_options = at::TensorOptions()
|
||||
.dtype(dtype)
|
||||
.layout(at::kStrided)
|
||||
.device(at::kCUDA)
|
||||
.requires_grad(false);
|
||||
const int param_elems = (quantize::requires_offset(quantType)) ? 2 : 1;
|
||||
auto params = torch::empty({groups, param_elems}, params_options);
|
||||
|
||||
auto output_options = at::TensorOptions()
|
||||
.dtype(at::kChar)
|
||||
.layout(at::kStrided)
|
||||
.device(at::kCUDA)
|
||||
.requires_grad(false);
|
||||
|
||||
auto output_sizes = input_vals.sizes().vec();
|
||||
output_sizes[output_sizes.size() - 1] /= numBits == 8 ? 1 : 2;
|
||||
auto output = torch::empty(output_sizes, output_options);
|
||||
|
||||
const int elems_per_group = at::numel(input_vals) / groups;
|
||||
|
||||
launch_quant((int8_t*)output.data_ptr(),
|
||||
(float*)params.data_ptr(),
|
||||
(__half*)input_vals.data_ptr(),
|
||||
groups,
|
||||
elems_per_group,
|
||||
numBits,
|
||||
quantType,
|
||||
at::cuda::getCurrentCUDAStream());
|
||||
|
||||
return {output, params};
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
at::Tensor dequantize(at::Tensor& quantized_data,
|
||||
at::Tensor& params,
|
||||
int groups,
|
||||
int num_bits,
|
||||
quantize::Type quant_type)
|
||||
{
|
||||
auto dtype = (std::is_same<T, float>::value) ? torch::kFloat32 : torch::kFloat16;
|
||||
auto output_options = at::TensorOptions()
|
||||
.dtype(dtype)
|
||||
.layout(at::kStrided)
|
||||
.device(at::kCUDA)
|
||||
.requires_grad(false);
|
||||
|
||||
auto output_sizes = quantized_data.sizes().vec();
|
||||
output_sizes[output_sizes.size() - 1] *= num_bits == 8 ? 1 : 2;
|
||||
auto output = torch::empty(output_sizes, output_options);
|
||||
|
||||
const int total_elems = at::numel(output);
|
||||
const int elems_per_group = total_elems / groups;
|
||||
|
||||
launch_dequantize_kernel((T*)output.data_ptr(),
|
||||
(const int8_t*)quantized_data.data_ptr(),
|
||||
(const float*)params.data_ptr(),
|
||||
quant_type,
|
||||
num_bits,
|
||||
elems_per_group,
|
||||
total_elems,
|
||||
at::cuda::getCurrentCUDAStream());
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
at::Tensor dequantize_int4_to_half_experimental(at::Tensor& data_in,
|
||||
at::Tensor& scale_buffer,
|
||||
at::Tensor& min_val_buffer,
|
||||
int num_group,
|
||||
int group_size)
|
||||
{
|
||||
auto output_options = at::TensorOptions().dtype(at::kHalf).device(at::kCUDA);
|
||||
auto output = torch::empty({num_group, group_size}, output_options);
|
||||
|
||||
launch_dequantize_int4_to_half_experimental((uint8_t*)data_in.data_ptr(),
|
||||
(half*)output.data_ptr(),
|
||||
(half*)scale_buffer.data_ptr(),
|
||||
(half*)min_val_buffer.data_ptr(),
|
||||
num_group,
|
||||
group_size,
|
||||
at::cuda::getCurrentCUDAStream());
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
at::Tensor dequantize_int8_to_half_experimental(at::Tensor& data_in,
|
||||
at::Tensor& scale_buffer,
|
||||
at::Tensor& min_val_buffer,
|
||||
int num_group,
|
||||
int group_size)
|
||||
{
|
||||
auto output_options = at::TensorOptions().dtype(at::kHalf).device(at::kCUDA);
|
||||
auto output = torch::empty({num_group, group_size}, output_options);
|
||||
|
||||
launch_dequantize_int8_to_half_experimental((uint8_t*)data_in.data_ptr(),
|
||||
(half*)output.data_ptr(),
|
||||
(half*)scale_buffer.data_ptr(),
|
||||
(half*)min_val_buffer.data_ptr(),
|
||||
num_group,
|
||||
group_size,
|
||||
at::cuda::getCurrentCUDAStream());
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
std::vector<at::Tensor> ds_swizzle_quant(at::Tensor& input_vals,
|
||||
int groups,
|
||||
int num_bits,
|
||||
quantize::Type quant_type,
|
||||
int pipeline_size,
|
||||
int nodes,
|
||||
int devices_per_node)
|
||||
{
|
||||
auto scales_options = at::TensorOptions()
|
||||
.dtype(at::kFloat)
|
||||
.layout(at::kStrided)
|
||||
.device(at::kCUDA)
|
||||
.requires_grad(false);
|
||||
const int scales_elems = (quantize::requires_offset(quant_type)) ? 2 : 1;
|
||||
auto scales = torch::empty({groups, scales_elems}, scales_options);
|
||||
|
||||
auto output_options = at::TensorOptions()
|
||||
.dtype(at::kChar)
|
||||
.layout(at::kStrided)
|
||||
.device(at::kCUDA)
|
||||
.requires_grad(false);
|
||||
|
||||
const int quantization_scalar = 8 / num_bits;
|
||||
const int compressed_vals = at::numel(input_vals) / quantization_scalar;
|
||||
|
||||
auto output = torch::empty({compressed_vals}, output_options);
|
||||
const int elems_per_group = at::numel(input_vals) / groups;
|
||||
|
||||
launch_swizzled_quant((int8_t*)output.data_ptr(),
|
||||
(float*)scales.data_ptr(),
|
||||
(__half*)input_vals.data_ptr(),
|
||||
num_bits,
|
||||
quant_type,
|
||||
groups,
|
||||
elems_per_group,
|
||||
pipeline_size,
|
||||
nodes,
|
||||
devices_per_node,
|
||||
at::cuda::getCurrentCUDAStream());
|
||||
|
||||
return {output, scales};
|
||||
}
|
||||
|
||||
std::vector<at::Tensor> quantized_reduction(at::Tensor& input_vals,
|
||||
at::Tensor& input_scales,
|
||||
int in_groups,
|
||||
int out_groups,
|
||||
int num_bits,
|
||||
quantize::Type quant_type,
|
||||
int devices_per_node)
|
||||
{
|
||||
auto scales_options = at::TensorOptions()
|
||||
.dtype(at::kFloat)
|
||||
.layout(at::kStrided)
|
||||
.device(at::kCUDA)
|
||||
.requires_grad(false);
|
||||
const int scales_elems = (quantize::requires_offset(quant_type)) ? 2 : 1;
|
||||
auto scales = torch::empty({out_groups, scales_elems}, scales_options);
|
||||
|
||||
auto output_options = at::TensorOptions()
|
||||
.dtype(at::kChar)
|
||||
.layout(at::kStrided)
|
||||
.device(at::kCUDA)
|
||||
.requires_grad(false);
|
||||
|
||||
std::vector<int64_t> sz_vector(input_vals.sizes().begin(), input_vals.sizes().end());
|
||||
sz_vector[sz_vector.size() - 1] = sz_vector.back() / devices_per_node; // num of GPU per nodes
|
||||
at::IntArrayRef sz(sz_vector);
|
||||
auto output = torch::empty(sz, output_options);
|
||||
|
||||
const int elems_per_in_tensor = at::numel(input_vals) / devices_per_node;
|
||||
const int elems_per_in_group = elems_per_in_tensor / (in_groups / devices_per_node);
|
||||
const int elems_per_out_group = elems_per_in_tensor / out_groups;
|
||||
|
||||
launch_dequant_reduce((int8_t*)output.data_ptr(),
|
||||
(float*)scales.data_ptr(),
|
||||
(const int8_t*)input_vals.data_ptr(),
|
||||
(const float*)input_scales.data_ptr(),
|
||||
devices_per_node,
|
||||
num_bits,
|
||||
quant_type,
|
||||
out_groups,
|
||||
elems_per_out_group,
|
||||
elems_per_in_tensor,
|
||||
in_groups / devices_per_node,
|
||||
elems_per_in_group,
|
||||
at::cuda::getCurrentCUDAStream());
|
||||
return {output, scales};
|
||||
}
|
||||
|
||||
PYBIND11_MODULE(TORCH_EXTENSION_NAME, m)
|
||||
{
|
||||
m.def("ds_quantize_fp32", &ds_quantize<float>, "DeepSpeed Quantize with fp32 (CUDA)");
|
||||
m.def("ds_quantize_fp16", &ds_quantize<__half>, "DeepSpeed Quantize with fp16 (CUDA)");
|
||||
m.def("ds_sr_quantize_fp32", &ds_sr_quantize<float>, "DeepSpeed Quantize with fp32 (CUDA)");
|
||||
m.def("ds_sr_quantize_fp16", &ds_sr_quantize<__half>, "DeepSpeed Quantize with fp16 (CUDA)");
|
||||
m.def("ds_quantize_asym_fp32", &ds_quantize_asym<float>, "DeepSpeed Quantize with fp32 (CUDA)");
|
||||
m.def(
|
||||
"ds_quantize_asym_fp16", &ds_quantize_asym<__half>, "DeepSpeed Quantize with fp16 (CUDA)");
|
||||
m.def("ds_sr_quantize_asym_fp32",
|
||||
&ds_sr_quantize_asym<float>,
|
||||
"DeepSpeed Quantize with fp32 (CUDA)");
|
||||
m.def("ds_sr_quantize_asym_fp16",
|
||||
&ds_sr_quantize_asym<__half>,
|
||||
"DeepSpeed Quantize with fp16 (CUDA)");
|
||||
pybind11::enum_<quantize::Type>(m, "QuantizationType")
|
||||
.value("Symmetric", quantize::Type::Symmetric)
|
||||
.value("Asymmetric", quantize::Type::Asymmetric)
|
||||
.export_values();
|
||||
m.def("quantize", &quantize_kernel);
|
||||
m.def("dequantize", &dequantize<__half>);
|
||||
m.def("dequantize_fp32", &dequantize<float>);
|
||||
m.def("dequantize_int4_to_half_experimental",
|
||||
&dequantize_int4_to_half_experimental,
|
||||
"Dequantize int4 to half (experimental)");
|
||||
m.def("dequantize_int8_to_half_experimental",
|
||||
&dequantize_int8_to_half_experimental,
|
||||
"Dequantize int8 to half (experimental)");
|
||||
m.def("swizzle_quant", &ds_swizzle_quant);
|
||||
m.def("quantized_reduction", &quantized_reduction);
|
||||
}
|
||||
@@ -1,161 +0,0 @@
|
||||
# Copyright (c) Microsoft Corporation.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
# DeepSpeed Team
|
||||
|
||||
import os
|
||||
import torch
|
||||
import deepspeed
|
||||
import subprocess
|
||||
import argparse
|
||||
import psutil
|
||||
from .ops.op_builder.all_ops import ALL_OPS
|
||||
from .git_version_info import installed_ops, torch_info
|
||||
from deepspeed.accelerator import get_accelerator
|
||||
|
||||
GREEN = '\033[92m'
|
||||
RED = '\033[91m'
|
||||
YELLOW = '\033[93m'
|
||||
END = '\033[0m'
|
||||
SUCCESS = f"{GREEN} [SUCCESS] {END}"
|
||||
OKAY = f"{GREEN}[OKAY]{END}"
|
||||
WARNING = f"{YELLOW}[WARNING]{END}"
|
||||
FAIL = f'{RED}[FAIL]{END}'
|
||||
INFO = '[INFO]'
|
||||
|
||||
color_len = len(GREEN) + len(END)
|
||||
okay = f"{GREEN}[OKAY]{END}"
|
||||
warning = f"{YELLOW}[WARNING]{END}"
|
||||
|
||||
|
||||
def op_report(verbose=True):
|
||||
max_dots = 23
|
||||
max_dots2 = 11
|
||||
h = ["op name", "installed", "compatible"]
|
||||
print("-" * (max_dots + max_dots2 + len(h[0]) + len(h[1])))
|
||||
print("DeepSpeed C++/CUDA extension op report")
|
||||
print("-" * (max_dots + max_dots2 + len(h[0]) + len(h[1])))
|
||||
|
||||
print("NOTE: Ops not installed will be just-in-time (JIT) compiled at\n"
|
||||
" runtime if needed. Op compatibility means that your system\n"
|
||||
" meet the required dependencies to JIT install the op.")
|
||||
|
||||
print("-" * (max_dots + max_dots2 + len(h[0]) + len(h[1])))
|
||||
print("JIT compiled ops requires ninja")
|
||||
ninja_status = OKAY if ninja_installed() else FAIL
|
||||
print('ninja', "." * (max_dots - 5), ninja_status)
|
||||
print("-" * (max_dots + max_dots2 + len(h[0]) + len(h[1])))
|
||||
print(h[0], "." * (max_dots - len(h[0])), h[1], "." * (max_dots2 - len(h[1])), h[2])
|
||||
print("-" * (max_dots + max_dots2 + len(h[0]) + len(h[1])))
|
||||
installed = f"{GREEN}[YES]{END}"
|
||||
no = f"{YELLOW}[NO]{END}"
|
||||
for op_name, builder in ALL_OPS.items():
|
||||
dots = "." * (max_dots - len(op_name))
|
||||
is_compatible = OKAY if builder.is_compatible(verbose) else no
|
||||
is_installed = installed if installed_ops.get(op_name, False) else no
|
||||
dots2 = '.' * ((len(h[1]) + (max_dots2 - len(h[1]))) - (len(is_installed) - color_len))
|
||||
print(op_name, dots, is_installed, dots2, is_compatible)
|
||||
print("-" * (max_dots + max_dots2 + len(h[0]) + len(h[1])))
|
||||
|
||||
|
||||
def ninja_installed():
|
||||
try:
|
||||
import ninja # noqa: F401 # type: ignore
|
||||
except ImportError:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def nvcc_version():
|
||||
import torch.utils.cpp_extension
|
||||
cuda_home = torch.utils.cpp_extension.CUDA_HOME
|
||||
if cuda_home is None:
|
||||
return f"{RED} [FAIL] cannot find CUDA_HOME via torch.utils.cpp_extension.CUDA_HOME={torch.utils.cpp_extension.CUDA_HOME} {END}"
|
||||
try:
|
||||
output = subprocess.check_output([cuda_home + "/bin/nvcc", "-V"], universal_newlines=True)
|
||||
except FileNotFoundError:
|
||||
return f"{RED} [FAIL] nvcc missing {END}"
|
||||
output_split = output.split()
|
||||
release_idx = output_split.index("release")
|
||||
release = output_split[release_idx + 1].replace(',', '').split(".")
|
||||
return ".".join(release)
|
||||
|
||||
|
||||
def get_shm_size():
|
||||
try:
|
||||
temp_dir = os.getenv('TEMP') or os.getenv('TMP') or os.path.join(os.path.expanduser('~'), 'tmp')
|
||||
shm_stats = psutil.disk_usage(temp_dir)
|
||||
shm_size = shm_stats.total
|
||||
shm_hbytes = human_readable_size(shm_size)
|
||||
warn = []
|
||||
if shm_size < 512 * 1024**2:
|
||||
warn.append(
|
||||
f" {YELLOW} [WARNING] Shared memory size might be too small, consider increasing it. {END}"
|
||||
)
|
||||
# Add additional warnings specific to your use case if needed.
|
||||
return shm_hbytes, warn
|
||||
except Exception as e:
|
||||
return "UNKNOWN", [f"Error getting shared memory size: {e}"]
|
||||
|
||||
|
||||
def human_readable_size(size):
|
||||
units = ['B', 'KB', 'MB', 'GB', 'TB']
|
||||
i = 0
|
||||
while size >= 1024 and i < len(units) - 1:
|
||||
size /= 1024
|
||||
i += 1
|
||||
return f'{size:.2f} {units[i]}'
|
||||
|
||||
|
||||
def debug_report():
|
||||
max_dots = 33
|
||||
|
||||
report = [("torch install path", torch.__path__), ("torch version", torch.__version__),
|
||||
("deepspeed install path", deepspeed.__path__),
|
||||
("deepspeed info", f"{deepspeed.__version__}, {deepspeed.__git_hash__}, {deepspeed.__git_branch__}")]
|
||||
if get_accelerator().device_name() == 'cuda':
|
||||
hip_version = getattr(torch.version, "hip", None)
|
||||
report.extend([("torch cuda version", torch.version.cuda), ("torch hip version", hip_version),
|
||||
("nvcc version", (None if hip_version else nvcc_version())),
|
||||
("deepspeed wheel compiled w.", f"torch {torch_info['version']}, " +
|
||||
(f"hip {torch_info['hip_version']}" if hip_version else f"cuda {torch_info['cuda_version']}"))
|
||||
])
|
||||
else:
|
||||
report.extend([("deepspeed wheel compiled w.", f"torch {torch_info['version']} ")])
|
||||
|
||||
report.append(("shared memory (/dev/shm) size", get_shm_size()))
|
||||
|
||||
print("DeepSpeed general environment info:")
|
||||
for name, value in report:
|
||||
warns = []
|
||||
if isinstance(value, tuple):
|
||||
value, warns = value
|
||||
print(name, "." * (max_dots - len(name)), value)
|
||||
if warns:
|
||||
for warn in warns:
|
||||
print(warn)
|
||||
|
||||
|
||||
def parse_arguments():
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('--hide_operator_status',
|
||||
action='store_true',
|
||||
help='Suppress display of installation and compatibility statuses of DeepSpeed operators. ')
|
||||
parser.add_argument('--hide_errors_and_warnings', action='store_true', help='Suppress warning and error messages.')
|
||||
args = parser.parse_args()
|
||||
return args
|
||||
|
||||
|
||||
def main(hide_operator_status=False, hide_errors_and_warnings=False):
|
||||
if not hide_operator_status:
|
||||
op_report(verbose=not hide_errors_and_warnings)
|
||||
debug_report()
|
||||
|
||||
|
||||
def cli_main():
|
||||
args = parse_arguments()
|
||||
main(hide_operator_status=args.hide_operator_status, hide_errors_and_warnings=args.hide_errors_and_warnings)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -1,18 +0,0 @@
|
||||
These are the modified files you would need for a MANUAL build of DeepSpeed 11.1 or 11.2.
|
||||
|
||||
They were created by a mix of instructions from erew123 and S95Sedan.
|
||||
|
||||
|
||||
- You still have to download the DeepSpeed v11.1 or v11.2 installation files from Microsoft to use these files.
|
||||
|
||||
https://github.com/microsoft/DeepSpeed/releases/tag/v0.11.2
|
||||
|
||||
|
||||
- These files were provided by S95Sedan here:
|
||||
|
||||
https://github.com/S95Sedan/Deepspeed-Windows
|
||||
|
||||
|
||||
- They are related to the manual build of DeepSpeed for AllTalk, which is linked here:
|
||||
|
||||
https://github.com/erew123/alltalk_tts/tree/main?tab=readme-ov-file#-option-2---a-bit-more-complicated
|
||||
@@ -0,0 +1,19 @@
|
||||
FROM nvidia/cuda:12.1.1-devel-ubuntu22.04
|
||||
ENV HOST 0.0.0.0
|
||||
RUN apt-get update && apt-get upgrade -y \
|
||||
&& apt-get install -y git build-essential portaudio19-dev \
|
||||
python3 python3-pip gcc wget \
|
||||
ocl-icd-opencl-dev opencl-headers clinfo \
|
||||
libclblast-dev libopenblas-dev libaio-dev \
|
||||
&& mkdir -p /etc/OpenCL/vendors && echo "libnvidia-opencl.so.1" > /etc/OpenCL/vendors/nvidia.icd \
|
||||
&& ln -s /usr/bin/python3 /usr/bin/python
|
||||
|
||||
WORKDIR /app
|
||||
COPY . .
|
||||
ENV CUDA_DOCKER_ARCH=all
|
||||
RUN pip install --no-cache-dir --no-deps -r system/requirements/requirements_docker.txt && \
|
||||
pip install --no-cache-dir deepspeed
|
||||
|
||||
EXPOSE 7851 7852
|
||||
RUN chmod +x launch.sh
|
||||
ENTRYPOINT ["sh", "-c", "./launch.sh"]
|
||||
@@ -0,0 +1,659 @@
|
||||
@echo off
|
||||
cd /D "%~dp0"
|
||||
setlocal enabledelayedexpansion
|
||||
@set "PATH=%PATH%;%SystemRoot%\system32"
|
||||
|
||||
:: Generate the ESC character
|
||||
for /F %%a in ('echo prompt $E ^| cmd') do set "ESC=%%a"
|
||||
|
||||
:: Standard Colors
|
||||
set "BLACK=%ESC%[30m"
|
||||
set "RED=%ESC%[31m"
|
||||
set "GREEN=%ESC%[32m"
|
||||
set "YELLOW=%ESC%[33m"
|
||||
set "BLUE=%ESC%[34m"
|
||||
set "MAGENTA=%ESC%[35m"
|
||||
set "CYAN=%ESC%[36m"
|
||||
set "WHITE=%ESC%[37m"
|
||||
set "L_BLACK=%ESC%[90m"
|
||||
set "L_RED=%ESC%[91m"
|
||||
set "L_GREEN=%ESC%[92m"
|
||||
set "L_YELLOW=%ESC%[93m"
|
||||
set "L_BLUE=%ESC%[94m"
|
||||
set "L_MAGENTA=%ESC%[95m"
|
||||
set "L_CYAN=%ESC%[96m"
|
||||
set "L_WHITE=%ESC%[97m"
|
||||
set "RESET=%ESC%[0m"
|
||||
|
||||
echo "%CD%"| findstr /C:" " >nul && echo. && echo %L_BLUE%ALLTALK WINDOWS SETUP UTILITY%RESET% && echo. && echo. && echo You are trying to install AllTalk in a folder that has a space in the folder path e.g. && echo. && echo C:\%L_RED%program files%RESET%\alltalk_tts && echo. && echo This causes errors with Conda and Python scripts. Please follow this link for reference: && echo. && echo %L_CYAN%https://docs.anaconda.com/free/working-with-conda/reference/faq/#installing-anaconda%RESET% && echo. && echo Please use a folder path that has no spaces in it e.g. && echo. && echo C:\myfiles\alltalk_tts\ && echo. && echo. && pause && goto :end
|
||||
|
||||
@rem Check for special characters in installation path
|
||||
set "SPCHARMESSAGE="WARNING: Special characters were detected in the installation path!" " This can cause the installation to fail!""
|
||||
echo "%CD%"| findstr /R /C:"[!#\$%&()\*+,;<=>?@\[\]\^`{|}~]" >nul && (
|
||||
call :PrintBigMessage %SPCHARMESSAGE%
|
||||
)
|
||||
set SPCHARMESSAGE=
|
||||
|
||||
@rem Check if curl is available
|
||||
curl --version >nul 2>&1
|
||||
if "%ERRORLEVEL%" NEQ "0" (
|
||||
echo curl is not available on this system. Please install curl then re-run the script https://curl.se/
|
||||
echo or perform a manual installation of a Conda Python environment.
|
||||
goto end
|
||||
)
|
||||
|
||||
:MainMenu
|
||||
cls
|
||||
echo.
|
||||
echo %L_BLUE%ALLTALK WINDOWS SETUP UTILITY%RESET%
|
||||
echo.
|
||||
echo INSTALLATION TYPE
|
||||
echo 1) I am using AllTalk as part of %L_GREEN%Text-generation-webui%RESET%
|
||||
echo 2) I am using AllTalk as a %L_GREEN%Standalone Application%RESET%
|
||||
echo.
|
||||
echo 9) %L_RED%Exit/Quit%RESET%
|
||||
echo.
|
||||
set /p UserOption=" Enter your choice: "
|
||||
|
||||
if "%UserOption%"=="1" goto WebUIMenu
|
||||
if "%UserOption%"=="2" goto StandaloneMenu
|
||||
if "%UserOption%"=="9" goto End
|
||||
goto MainMenu
|
||||
|
||||
:WebUIMenu
|
||||
cls
|
||||
echo.
|
||||
echo %L_BLUE%TEXT-GENERATION-WEBUI SETUP%RESET%
|
||||
echo.
|
||||
echo Please ensure you have started your Text-generation-webui Python
|
||||
echo environment. If you have NOT done this, please run %L_GREEN%cmd_windows.bat%RESET%
|
||||
echo in the %L_GREEN%text-generation-webui%RESET% folder and then re-run this script.
|
||||
echo.
|
||||
echo BASE REQUIREMENTS
|
||||
echo 1) Apply/Re-Apply the requirements for %L_GREEN%Text-generation-webui%RESET%.
|
||||
echo.
|
||||
echo OPTIONAL
|
||||
echo 2) Git Pull the latest AllTalk updates from Github
|
||||
echo.
|
||||
echo DEEPSPEED FOR %L_YELLOW=%PyTorch 2.1.x%RESET%
|
||||
echo 4) Install DeepSpeed v11.2 for CUDA %L_GREEN%11.8%RESET% and Python-3.11.x and %L_YELLOW%PyTorch 2.1.x%RESET%.
|
||||
echo 5) Install DeepSpeed v11.2 for CUDA %L_GREEN%12.1%RESET% and Python-3.11.x and %L_YELLOW%PyTorch 2.1.x%RESET%.
|
||||
echo.
|
||||
echo DEEPSPEED FOR %L_YELLOW=%PyTorch 2.2.x%RESET% (March 2024 builds of Text-gen-webui and later)
|
||||
echo 6) Install DeepSpeed v14.0 for CUDA %L_GREEN%12.1%RESET% and Python-3.11.x and %L_YELLOW%PyTorch 2.2.x%RESET%.
|
||||
echo 7) Install DeepSpeed v14.0 for CUDA %L_GREEN%11.8%RESET% and Python-3.11.x and %L_YELLOW%PyTorch 2.2.x%RESET%.
|
||||
echo.
|
||||
echo U) Uninstall DeepSpeed.
|
||||
echo.
|
||||
echo. OTHER
|
||||
echo 8) Generate a diagnostics file.
|
||||
echo.
|
||||
echo 9) %L_RED%Exit/Quit%RESET%
|
||||
echo.
|
||||
set /p WebUIOption="Enter your choice: "
|
||||
if "%WebUIOption%"=="1" goto InstallNvidiaTextGen
|
||||
if "%WebUIOption%"=="2" goto TGGitpull
|
||||
if "%WebUIOption%"=="4" goto InstallDeepSpeed118TextGen
|
||||
if "%WebUIOption%"=="5" goto InstallDeepSpeed121TextGen
|
||||
if "%WebUIOption%"=="6" goto InstallDeepSpeed121TextGenPytorch221
|
||||
if "%WebUIOption%"=="7" goto InstallDeepSpeed118TextGenPytorch221
|
||||
if "%WebUIOption%"=="U" goto UnInstallDeepSpeed
|
||||
if "%WebUIOption%"=="u" goto UnInstallDeepSpeed
|
||||
if "%WebUIOption%"=="8" goto GenerateDiagsTextGen
|
||||
if "%WebUIOption%"=="9" goto End
|
||||
goto WebUIMenu
|
||||
|
||||
:StandaloneMenu
|
||||
cls
|
||||
echo.
|
||||
echo %L_BLUE%ALLTALK STANDALONE APPLICATION SETUP%RESET%
|
||||
echo.
|
||||
echo BASE REQUIREMENTS
|
||||
echo 1) Install AllTalk as a Standalone Application
|
||||
echo.
|
||||
echo OPTIONAL
|
||||
echo 2) Git Pull the latest AllTalk updates from Github
|
||||
echo 3) Re-Apply/Update the requirements file
|
||||
echo 4) Delete AllTalk's custom Python environment
|
||||
echo 5) Purge the PIP cache
|
||||
echo.
|
||||
echo. OTHER
|
||||
echo 8) Generate a diagnostics file
|
||||
echo.
|
||||
echo 9) %L_RED%Exit/Quit%RESET%
|
||||
echo.
|
||||
set /p StandaloneOption="Enter your choice: "
|
||||
if "%StandaloneOption%"=="1" goto InstallCustomStandalone
|
||||
if "%StandaloneOption%"=="2" goto STGitpull
|
||||
if "%StandaloneOption%"=="3" goto STReapplyrequirements
|
||||
if "%StandaloneOption%"=="4" goto STDeleteCustomStandalone
|
||||
if "%StandaloneOption%"=="5" goto STPurgepipcache
|
||||
if "%StandaloneOption%"=="8" goto GenerateDiagsStandalone
|
||||
if "%StandaloneOption%"=="9" goto EndStandalone
|
||||
goto StandaloneMenu
|
||||
|
||||
:InstallNvidiaTextGen
|
||||
pip install -r system\requirements\requirements_textgen.txt
|
||||
if %ERRORLEVEL% neq 0 (
|
||||
echo.
|
||||
echo There was an error installing the requirements.
|
||||
echo Have you started your Text-gen-webui Python environment
|
||||
echo with cmd_{yourOS} before running atsetup.bat?
|
||||
echo Press any key to return to the menu.
|
||||
echo.
|
||||
pause
|
||||
goto WebUIMenu
|
||||
)
|
||||
Echo.
|
||||
echo.
|
||||
Echo Requirements installed successfully.
|
||||
Echo.
|
||||
pause
|
||||
goto WebUIMenu
|
||||
|
||||
:TGGitpull
|
||||
git pull
|
||||
if %ERRORLEVEL% neq 0 (
|
||||
echo.
|
||||
echo There was an error pulling from Github.
|
||||
echo Press any key to return to the menu.
|
||||
echo.
|
||||
pause
|
||||
goto WebUIMenu
|
||||
)
|
||||
Echo.
|
||||
echo AllTalk Updated from Github. Please re-apply
|
||||
echo the latest requirements file. Option 1
|
||||
Echo.
|
||||
pause
|
||||
goto WebUIMenu
|
||||
|
||||
:InstallDeepSpeed118TextGen
|
||||
echo Downloading DeepSpeed...
|
||||
curl -LO https://github.com/erew123/alltalk_tts/releases/download/deepspeed/deepspeed-0.11.2+cuda118-cp311-cp311-win_amd64.whl
|
||||
if %ERRORLEVEL% neq 0 (
|
||||
echo.
|
||||
echo Failed to download DeepSpeed wheel file.
|
||||
echo Please check your internet connection or try again later.
|
||||
echo Press any key to return to the menu.
|
||||
echo.
|
||||
pause
|
||||
goto WebUIMenu
|
||||
)
|
||||
echo DeepSpeed wheel file downloaded successfully.
|
||||
echo Installing DeepSpeed...
|
||||
pip install deepspeed-0.11.2+cuda118-cp311-cp311-win_amd64.whl
|
||||
if %ERRORLEVEL% neq 0 (
|
||||
echo.
|
||||
echo Failed to install DeepSpeed.
|
||||
echo Please check if the wheel file is compatible with your system.
|
||||
echo Press any key to return to the menu.
|
||||
echo.
|
||||
pause
|
||||
goto WebUIMenu
|
||||
)
|
||||
Echo.
|
||||
echo.
|
||||
Echo DeepSpeed installed successfully.
|
||||
Echo.
|
||||
del deepspeed-0.11.2+cuda118-cp311-cp311-win_amd64.whl
|
||||
pause
|
||||
goto WebUIMenu
|
||||
|
||||
:InstallDeepSpeed121TextGen
|
||||
echo Downloading DeepSpeed...
|
||||
curl -LO https://github.com/erew123/alltalk_tts/releases/download/deepspeed/deepspeed-0.11.2+cuda121-cp311-cp311-win_amd64.whl
|
||||
if %ERRORLEVEL% neq 0 (
|
||||
echo.
|
||||
echo Failed to download DeepSpeed wheel file.
|
||||
echo Please check your internet connection or try again later.
|
||||
echo Press any key to return to the menu.
|
||||
echo.
|
||||
pause
|
||||
goto WebUIMenu
|
||||
)
|
||||
echo DeepSpeed wheel file downloaded successfully.
|
||||
echo Installing DeepSpeed...
|
||||
pip install deepspeed-0.11.2+cuda121-cp311-cp311-win_amd64.whl
|
||||
if %ERRORLEVEL% neq 0 (
|
||||
echo.
|
||||
echo Failed to install DeepSpeed.
|
||||
echo Please check if the wheel file is compatible with your system.
|
||||
echo Press any key to return to the menu.
|
||||
echo.
|
||||
pause
|
||||
goto WebUIMenu
|
||||
)
|
||||
Echo.
|
||||
echo.
|
||||
Echo DeepSpeed installed successfully.
|
||||
Echo.
|
||||
del deepspeed-0.11.2+cuda121-cp311-cp311-win_amd64.whl
|
||||
pause
|
||||
goto WebUIMenu
|
||||
|
||||
:InstallDeepSpeed121TextGenPytorch221
|
||||
echo Downloading DeepSpeed...
|
||||
curl -LO https://github.com/erew123/alltalk_tts/releases/download/DeepSpeed-14.0/deepspeed-0.14.0+ce78a63-cp311-cp311-win_amd64.whl
|
||||
if %ERRORLEVEL% neq 0 (
|
||||
echo.
|
||||
echo Failed to download DeepSpeed wheel file.
|
||||
echo Please check your internet connection or try again later.
|
||||
echo Press any key to return to the menu.
|
||||
echo.
|
||||
pause
|
||||
goto WebUIMenu
|
||||
)
|
||||
echo DeepSpeed wheel file downloaded successfully.
|
||||
echo Installing DeepSpeed...
|
||||
pip install deepspeed-0.14.0+ce78a63-cp311-cp311-win_amd64.whl
|
||||
if %ERRORLEVEL% neq 0 (
|
||||
echo.
|
||||
echo Failed to install DeepSpeed.
|
||||
echo Please check if the wheel file is compatible with your system.
|
||||
echo Press any key to return to the menu.
|
||||
echo.
|
||||
pause
|
||||
goto WebUIMenu
|
||||
)
|
||||
Echo.
|
||||
echo.
|
||||
Echo DeepSpeed installed successfully.
|
||||
Echo.
|
||||
del deepspeed-0.14.0+ce78a63-cp311-cp311-win_amd64.whl
|
||||
pause
|
||||
goto WebUIMenu
|
||||
|
||||
:InstallDeepSpeed118TextGenPytorch221
|
||||
echo Downloading DeepSpeed...
|
||||
curl -LO https://github.com/erew123/alltalk_tts/releases/download/DeepSpeed-14.0/deepspeed-0.14.0+cu118-cp311-cp311-win_amd64.whl
|
||||
if %ERRORLEVEL% neq 0 (
|
||||
echo.
|
||||
echo Failed to download DeepSpeed wheel file.
|
||||
echo Please check your internet connection or try again later.
|
||||
echo Press any key to return to the menu.
|
||||
echo.
|
||||
pause
|
||||
goto WebUIMenu
|
||||
)
|
||||
echo DeepSpeed wheel file downloaded successfully.
|
||||
echo Installing DeepSpeed...
|
||||
pip install deepspeed-0.14.0+cu118-cp311-cp311-win_amd64.whl
|
||||
if %ERRORLEVEL% neq 0 (
|
||||
echo.
|
||||
echo Failed to install DeepSpeed.
|
||||
echo Please check if the wheel file is compatible with your system.
|
||||
echo Press any key to return to the menu.
|
||||
echo.
|
||||
pause
|
||||
goto WebUIMenu
|
||||
)
|
||||
Echo.
|
||||
echo.
|
||||
Echo DeepSpeed installed successfully.
|
||||
Echo.
|
||||
del deepspeed-0.14.0+cu118-cp311-cp311-win_amd64.whl
|
||||
pause
|
||||
goto WebUIMenu
|
||||
|
||||
:UnInstallDeepSpeed
|
||||
pip uninstall deepspeed
|
||||
if %ERRORLEVEL% neq 0 (
|
||||
echo.
|
||||
echo There was an error uninstalling DeepSpeed.
|
||||
echo Press any key to return to the menu.
|
||||
echo.
|
||||
pause
|
||||
goto WebUIMenu
|
||||
)
|
||||
echo.
|
||||
Echo DeepSpeed uninstalled successfully.
|
||||
Echo.
|
||||
pause
|
||||
goto WebUIMenu
|
||||
|
||||
:GenerateDiagsTextGen
|
||||
Python diagnostics.py
|
||||
if %ERRORLEVEL% neq 0 (
|
||||
echo.
|
||||
echo There was an error running diagnostics. Have you correctly started your
|
||||
echo Text-generation-webui Python environment with %L_GREEN%cmd_windows.bat%RESET%?
|
||||
echo.
|
||||
pause
|
||||
goto WebUIMenu
|
||||
)
|
||||
Echo.
|
||||
echo.
|
||||
Echo Diagnostics.log generated. Please scroll up to look over the log.
|
||||
Echo.
|
||||
pause
|
||||
goto WebUIMenu
|
||||
|
||||
:InstallCustomStandalone
|
||||
set PATH=%PATH%;%SystemRoot%\system32
|
||||
|
||||
@rem Check if curl is available
|
||||
curl --version >nul 2>&1
|
||||
if "%ERRORLEVEL%" NEQ "0" (
|
||||
echo curl is not available on this system. Please install curl then re-run the script https://curl.se/
|
||||
echo or perform a manual installation of a Conda Python environment.
|
||||
goto end
|
||||
)
|
||||
echo "%CD%"| findstr /C:" " >nul && echo This script relies on Miniconda which can not be silently installed under a path with spaces. Please correct your folder names and re-try installation. && goto exit
|
||||
|
||||
@rem Check for special characters in installation path
|
||||
set "SPCHARMESSAGE=WARNING: Special characters were detected in the installation path! This can cause the installation to fail!"
|
||||
echo "%CD%"| findstr /R /C:"[!#\$%&()\*+,;<=>?@\[\]\^`{|}~]" >nul && (
|
||||
call :PrintBigMessage %SPCHARMESSAGE%
|
||||
)
|
||||
set SPCHARMESSAGE=
|
||||
|
||||
@rem fix failed install when installing to a separate drive
|
||||
set TMP=%cd%\alltalk_environment
|
||||
set TEMP=%cd%\alltalk_environment
|
||||
|
||||
@rem deactivate existing conda envs as needed to avoid conflicts
|
||||
(call conda deactivate && call conda deactivate && call conda deactivate) 2>nul
|
||||
|
||||
@rem config
|
||||
set INSTALL_DIR=%cd%\alltalk_environment
|
||||
set CONDA_ROOT_PREFIX=%cd%\alltalk_environment\conda
|
||||
set INSTALL_ENV_DIR=%cd%\alltalk_environment\env
|
||||
set MINICONDA_DOWNLOAD_URL=https://repo.anaconda.com/miniconda/Miniconda3-py310_23.3.1-0-Windows-x86_64.exe
|
||||
set conda_exists=F
|
||||
|
||||
@rem figure out whether git and conda need to be installed
|
||||
call "%CONDA_ROOT_PREFIX%\_conda.exe" --version >nul 2>&1
|
||||
if "%ERRORLEVEL%" EQU "0" (
|
||||
set conda_exists=T
|
||||
call "%CONDA_ROOT_PREFIX%\condabin\conda.bat" activate "%INSTALL_ENV_DIR%"
|
||||
goto RunScript
|
||||
)
|
||||
|
||||
@rem download and install conda if not installed
|
||||
echo Downloading Miniconda from %MINICONDA_DOWNLOAD_URL% to %INSTALL_DIR%\miniconda_installer.exe
|
||||
mkdir "%INSTALL_DIR%"
|
||||
call curl -Lk "%MINICONDA_DOWNLOAD_URL%" > "%INSTALL_DIR%\miniconda_installer.exe" || ( echo. && echo Miniconda failed to download. && goto end )
|
||||
echo Installing Miniconda to %CONDA_ROOT_PREFIX%
|
||||
start /wait "" "%INSTALL_DIR%\miniconda_installer.exe" /InstallationType=JustMe /NoShortcuts=1 /AddToPath=0 /RegisterPython=0 /NoRegistry=1 /S /D=%CONDA_ROOT_PREFIX%
|
||||
echo Miniconda version:
|
||||
call "%CONDA_ROOT_PREFIX%\_conda.exe" --version || ( echo. && echo Miniconda not found. && goto end )
|
||||
|
||||
@rem create the installer env
|
||||
echo Packages to install: %PACKAGES_TO_INSTALL%
|
||||
call "%CONDA_ROOT_PREFIX%\_conda.exe" create --no-shortcuts -y -k --prefix "%INSTALL_ENV_DIR%" python=3.11 || ( echo. && echo Conda environment creation failed. && goto end )
|
||||
|
||||
@rem check if conda environment was actually created
|
||||
if not exist "%INSTALL_ENV_DIR%\python.exe" ( echo. && echo Conda environment is empty. && goto end )
|
||||
|
||||
@rem activate installer env
|
||||
call "%CONDA_ROOT_PREFIX%\condabin\conda.bat" activate "%INSTALL_ENV_DIR%" || ( echo. && echo Miniconda hook not found. && goto end )
|
||||
|
||||
echo.
|
||||
echo Downloading and installing PyTorch. This step can take a long time
|
||||
echo depending on your internet connection and hard drive speed. Please
|
||||
echo be patient.
|
||||
echo.
|
||||
pip install torch==2.2.2+cu121 torchaudio>=2.2.2+cu121 --upgrade --force-reinstall --extra-index-url https://download.pytorch.org/whl/cu121
|
||||
echo Installing other requirements.
|
||||
echo.
|
||||
pip install -r system\requirements\requirements_standalone.txt
|
||||
curl -LO https://github.com/erew123/alltalk_tts/releases/download/DeepSpeed-14.0/deepspeed-0.14.0+ce78a63-cp311-cp311-win_amd64.whl
|
||||
echo Installing DeepSpeed...
|
||||
pip install deepspeed-0.14.0+ce78a63-cp311-cp311-win_amd64.whl
|
||||
del deepspeed-0.14.0+ce78a63-cp311-cp311-win_amd64.whl
|
||||
|
||||
|
||||
@rem Create start_environment.bat to run AllTalk environment
|
||||
echo @echo off > start_environment.bat
|
||||
echo cd /D "%~dp0" >> start_environment.bat
|
||||
echo set CONDA_ROOT_PREFIX=%cd%\alltalk_environment\conda >> start_environment.bat
|
||||
echo set INSTALL_ENV_DIR=%cd%\alltalk_environment\env >> start_environment.bat
|
||||
echo call "%CONDA_ROOT_PREFIX%\condabin\conda.bat" activate "%INSTALL_ENV_DIR%" >> start_environment.bat
|
||||
@rem Create start_alltalk.bat to run AllTalk
|
||||
echo @echo off > start_alltalk.bat
|
||||
echo cd /D "%~dp0" >> start_alltalk.bat
|
||||
echo set CONDA_ROOT_PREFIX=%cd%\alltalk_environment\conda >> start_alltalk.bat
|
||||
echo set INSTALL_ENV_DIR=%cd%\alltalk_environment\env >> start_alltalk.bat
|
||||
echo call "%CONDA_ROOT_PREFIX%\condabin\conda.bat" activate "%INSTALL_ENV_DIR%" >> start_alltalk.bat
|
||||
echo call python script.py >> start_alltalk.bat
|
||||
@rem Create start_finetune.bat to run AllTalk
|
||||
echo @echo off > start_finetune.bat
|
||||
echo cd /D "%~dp0" >> start_finetune.bat
|
||||
echo set CONDA_ROOT_PREFIX=%cd%\alltalk_environment\conda >> start_finetune.bat
|
||||
echo set INSTALL_ENV_DIR=%cd%\alltalk_environment\env >> start_finetune.bat
|
||||
echo call "%CONDA_ROOT_PREFIX%\condabin\conda.bat" activate "%INSTALL_ENV_DIR%" >> start_finetune.bat
|
||||
echo call python finetune.py >> start_finetune.bat
|
||||
Echo.
|
||||
Echo Run %L_YELLOW%start_alltalk.bat%RESET% to start AllTalk.
|
||||
Echo Run %L_YELLOW%start_finetune.bat%RESET% to start Finetuning.
|
||||
Echo Run %L_YELLOW%start_environment.bat%RESET% to start the AllTalk Python environment.
|
||||
Echo.
|
||||
pause
|
||||
goto StandaloneMenu
|
||||
|
||||
:STDeleteCustomStandalone
|
||||
@rem Check if the alltalk_environment directory exists
|
||||
if not exist "%cd%\alltalk_environment\" (
|
||||
echo.
|
||||
echo %L_GREEN%alltalk_environment%RESET% directory does not exist. No need to delete.
|
||||
echo.
|
||||
pause
|
||||
goto StandaloneMenu
|
||||
)
|
||||
@rem Check if a Conda environment is active
|
||||
if not defined CONDA_PREFIX goto NoCondaEnvDeleteCustomStandalone
|
||||
@rem Deactivate Conda environment if it's active
|
||||
Echo Exiting the Conda Environment. Please run %L_GREEN%atsetup.bat%RESET% again and delete the environment.
|
||||
conda deactivate
|
||||
:NoCondaEnvDeleteCustomStandalone
|
||||
echo Deleting "alltalk_environment". Please wait.
|
||||
rd /s /q "alltalk_environment"
|
||||
del start_alltalk.bat
|
||||
del start_environment.bat
|
||||
if %ERRORLEVEL% neq 0 (
|
||||
echo.
|
||||
echo Failed to delete alltalk_environment folder.
|
||||
echo Please make sure it is not in use and try again.
|
||||
echo.
|
||||
pause
|
||||
goto StandaloneMenu
|
||||
)
|
||||
echo.
|
||||
Echo.
|
||||
echo Environment %L_GREEN%alltalk_environment%RESET% deleted. Please set up the environment again.
|
||||
Echo.
|
||||
pause
|
||||
goto StandaloneMenu
|
||||
|
||||
:GenerateDiagsStandalone
|
||||
cd /D "%~dp0"
|
||||
set CONDA_ROOT_PREFIX=%cd%\alltalk_environment\conda
|
||||
set INSTALL_ENV_DIR=%cd%\alltalk_environment\env
|
||||
@rem Check if the Conda environment exists
|
||||
if not exist "%INSTALL_ENV_DIR%\python.exe" (
|
||||
echo.
|
||||
echo The Conda environment at "%INSTALL_ENV_DIR%" does not exist.
|
||||
echo Please install the environment before proceeding.
|
||||
echo.
|
||||
pause
|
||||
goto StandaloneMenu
|
||||
)
|
||||
@rem Attempt to activate the Conda environment
|
||||
call "%CONDA_ROOT_PREFIX%\condabin\conda.bat" activate "%INSTALL_ENV_DIR%"
|
||||
if errorlevel 1 (
|
||||
echo.
|
||||
echo Failed to activate the Conda environment.
|
||||
echo Please check your installation and try again.
|
||||
echo.
|
||||
pause
|
||||
goto StandaloneMenu
|
||||
)
|
||||
@rem Run diagnostics
|
||||
Python diagnostics.py
|
||||
if %ERRORLEVEL% neq 0 (
|
||||
echo.
|
||||
echo There was an error running diagnostics.
|
||||
echo Press any key to return to the menu.
|
||||
echo.
|
||||
pause
|
||||
goto StandaloneMenu
|
||||
)
|
||||
Echo.
|
||||
Echo.
|
||||
Echo Diagnostics.log generated. Please scroll up to look over the log.
|
||||
Echo.
|
||||
pause
|
||||
goto StandaloneMenu
|
||||
|
||||
:STReapplyrequirements
|
||||
cd /D "%~dp0"
|
||||
set CONDA_ROOT_PREFIX=%cd%\alltalk_environment\conda
|
||||
set INSTALL_ENV_DIR=%cd%\alltalk_environment\env
|
||||
@rem Check if the Conda environment exists
|
||||
if not exist "%INSTALL_ENV_DIR%\python.exe" (
|
||||
echo.
|
||||
echo The Conda environment at "%INSTALL_ENV_DIR%" does not exist.
|
||||
echo Please install the environment before proceeding.
|
||||
echo.
|
||||
pause
|
||||
goto StandaloneMenu
|
||||
)
|
||||
@rem Attempt to activate the Conda environment
|
||||
call "%CONDA_ROOT_PREFIX%\condabin\conda.bat" activate "%INSTALL_ENV_DIR%"
|
||||
if errorlevel 1 (
|
||||
echo.
|
||||
echo Failed to activate the Conda environment.
|
||||
echo Please check your installation and try again.
|
||||
echo.
|
||||
pause
|
||||
goto StandaloneMenu
|
||||
)
|
||||
@rem Run Reapply requirements
|
||||
echo.
|
||||
echo Downloading and installing PyTorch. This step can take a long time
|
||||
echo depending on your internet connection and hard drive speed. Please
|
||||
echo be patient.
|
||||
echo.
|
||||
pip install torch==2.2.2+cu121 torchaudio>=2.2.2+cu121 --upgrade --force-reinstall --extra-index-url https://download.pytorch.org/whl/cu121
|
||||
echo Installing other requirements.
|
||||
echo.
|
||||
pip install -r system\requirements\requirements_standalone.txt
|
||||
C:/Windows/system32/curl.exe -LO https://github.com/erew123/alltalk_tts/releases/download/DeepSpeed-14.0/deepspeed-0.14.0+ce78a63-cp311-cp311-win_amd64.whl
|
||||
echo Installing DeepSpeed...
|
||||
pip install deepspeed-0.14.0+ce78a63-cp311-cp311-win_amd64.whl
|
||||
del deepspeed-0.14.0+ce78a63-cp311-cp311-win_amd64.whl
|
||||
if %ERRORLEVEL% neq 0 (
|
||||
echo.
|
||||
echo There was an error.
|
||||
echo Press any key to return to the menu.
|
||||
echo.
|
||||
pause
|
||||
goto StandaloneMenu
|
||||
)
|
||||
Echo.
|
||||
Echo.
|
||||
Echo Requirements have been re-applied/updated.
|
||||
Echo.
|
||||
pause
|
||||
goto StandaloneMenu
|
||||
|
||||
:STPurgepipcache
|
||||
cd /D "%~dp0"
|
||||
set CONDA_ROOT_PREFIX=%cd%\alltalk_environment\conda
|
||||
set INSTALL_ENV_DIR=%cd%\alltalk_environment\env
|
||||
@rem Check if the Conda environment exists
|
||||
if not exist "%INSTALL_ENV_DIR%\python.exe" (
|
||||
echo.
|
||||
echo The Conda environment at "%INSTALL_ENV_DIR%" does not exist.
|
||||
echo Please install the environment before proceeding.
|
||||
echo.
|
||||
pause
|
||||
goto StandaloneMenu
|
||||
)
|
||||
@rem Attempt to activate the Conda environment
|
||||
call "%CONDA_ROOT_PREFIX%\condabin\conda.bat" activate "%INSTALL_ENV_DIR%"
|
||||
if errorlevel 1 (
|
||||
echo.
|
||||
echo Failed to activate the Conda environment.
|
||||
echo Please check your installation and try again.
|
||||
echo.
|
||||
pause
|
||||
goto StandaloneMenu
|
||||
)
|
||||
@rem Clear the PIP cache
|
||||
echo.
|
||||
echo Purging the PIP cache of downloaded files.
|
||||
echo.
|
||||
pip cache purge
|
||||
if %ERRORLEVEL% neq 0 (
|
||||
echo.
|
||||
echo There was an error.
|
||||
echo Press any key to return to the menu.
|
||||
echo.
|
||||
pause
|
||||
goto StandaloneMenu
|
||||
)
|
||||
Echo.
|
||||
Echo The PIP cache has been purged.
|
||||
Echo.
|
||||
pause
|
||||
goto StandaloneMenu
|
||||
|
||||
:STGitpull
|
||||
cd /D "%~dp0"
|
||||
set CONDA_ROOT_PREFIX=%cd%\alltalk_environment\conda
|
||||
set INSTALL_ENV_DIR=%cd%\alltalk_environment\env
|
||||
@rem Check if the Conda environment exists
|
||||
if not exist "%INSTALL_ENV_DIR%\python.exe" (
|
||||
echo.
|
||||
echo The Conda environment at "%INSTALL_ENV_DIR%" does not exist.
|
||||
echo Please install the environment before proceeding.
|
||||
echo.
|
||||
pause
|
||||
goto StandaloneMenu
|
||||
)
|
||||
@rem Attempt to activate the Conda environment
|
||||
call "%CONDA_ROOT_PREFIX%\condabin\conda.bat" activate "%INSTALL_ENV_DIR%"
|
||||
if errorlevel 1 (
|
||||
echo.
|
||||
echo Failed to activate the Conda environment.
|
||||
echo Please check your installation and try again.
|
||||
echo.
|
||||
pause
|
||||
goto StandaloneMenu
|
||||
)
|
||||
@rem Pull from Github
|
||||
echo.
|
||||
echo Pulling the latest updates. Please re-apply
|
||||
echo the latest requirements file. Option 3
|
||||
echo.
|
||||
git pull
|
||||
if %ERRORLEVEL% neq 0 (
|
||||
echo.
|
||||
echo There was an error pulling from Github.
|
||||
echo Press any key to return to the menu.
|
||||
echo.
|
||||
pause
|
||||
goto StandaloneMenu
|
||||
)
|
||||
Echo.
|
||||
echo AllTalk Updated from Github. Please re-apply
|
||||
echo the latest requirements file. Option 3
|
||||
Echo.
|
||||
pause
|
||||
goto StandaloneMenu
|
||||
|
||||
:EndStandalone
|
||||
echo Exiting AllTalk Setup Utility...
|
||||
echo.
|
||||
Echo Remember, after installation you can....
|
||||
Echo Run %L_YELLOW%start_alltalk.bat%RESET% to start AllTalk.
|
||||
Echo Run %L_YELLOW%start_finetune.bat%RESET% to start Finetuning.
|
||||
Echo Run %L_YELLOW%start_environment.bat%RESET% to start the AllTalk Python environment.
|
||||
Echo.
|
||||
exit /b
|
||||
|
||||
:End
|
||||
echo Exiting AllTalk Setup Utility...
|
||||
exit /b
|
||||
@@ -0,0 +1,520 @@
|
||||
#!/bin/bash
|
||||
|
||||
# ANSI color codes
|
||||
RED='\033[1;31m'
|
||||
GREEN='\033[1;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[1;34m'
|
||||
CYAN='\033[1;36m'
|
||||
MAGENTA='\033[1;35m'
|
||||
WHITE='\033[1;37m'
|
||||
L_RED='\033[1;91m'
|
||||
L_GREEN='\033[1;92m'
|
||||
L_YELLOW='\033[1;93m'
|
||||
L_BLUE='\033[1;94m'
|
||||
L_CYAN='\033[1;96m'
|
||||
L_MAGENTA='\033[1;95m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Navigate to the script's directory
|
||||
cd "$(dirname "$0")"
|
||||
|
||||
# Function to check if curl is installed
|
||||
check_curl() {
|
||||
if ! command -v curl &> /dev/null; then
|
||||
echo "curl is not available on this system. Please install curl then re-run the script https://curl.se/"
|
||||
echo "or perform a manual installation of a Conda Python environment."
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Check if the current directory path contains a space
|
||||
containsSpace=false
|
||||
currentPath=$(pwd)
|
||||
if echo "$currentPath" | grep -q ' '; then
|
||||
containsSpace=true
|
||||
fi
|
||||
|
||||
if [ "$containsSpace" = true ]; then
|
||||
echo
|
||||
echo -e " ${L_BLUE}ALLTALK LINUX SETUP UTILITY${NC}"
|
||||
echo
|
||||
echo
|
||||
echo -e " You are trying to install AllTalk in a folder that has a space in the"
|
||||
echo -e " folder path e.g."
|
||||
echo
|
||||
echo -e " /home/${L_RED}program files${NC}/alltalk_tts"
|
||||
echo
|
||||
echo -e " This causes errors with Conda and Python scripts. Please follow this"
|
||||
echo -e " link for reference:"
|
||||
echo
|
||||
echo -e " ${L_CYAN}https://docs.anaconda.com/free/working-with-conda/reference/faq/#installing-anaconda${NC}"
|
||||
echo
|
||||
echo -e " Please use a folder path that has no spaces in it e.g."
|
||||
echo
|
||||
echo -e " /home/myfiles/alltalk_tts/"
|
||||
echo
|
||||
echo
|
||||
read -p "Press Enter to continue..."
|
||||
exit 1
|
||||
else
|
||||
# Continue with the main menu
|
||||
echo "Continue with the main menu."
|
||||
fi
|
||||
|
||||
# Main Menu
|
||||
main_menu() {
|
||||
while true; do
|
||||
clear
|
||||
echo
|
||||
echo -e " ${L_BLUE}ALLTALK LINUX SETUP UTILITY${NC}"
|
||||
echo
|
||||
echo " INSTALLATION TYPE"
|
||||
echo -e " 1) I am using AllTalk as part of ${L_GREEN}Text-generation-webui${NC}"
|
||||
echo -e " 2) I am using AllTalk as a ${L_GREEN}Standalone Application${NC}"
|
||||
echo
|
||||
echo -e " 9)${L_RED} Exit/Quit${NC}"
|
||||
echo
|
||||
read -p " Enter your choice: " user_option
|
||||
|
||||
case $user_option in
|
||||
1) webui_menu ;;
|
||||
2) standalone_menu ;;
|
||||
9) exit 0 ;;
|
||||
*) echo "Invalid option"; sleep 2 ;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
# Text-generation-webui Menu
|
||||
webui_menu() {
|
||||
while true; do
|
||||
clear
|
||||
echo
|
||||
echo -e " ${L_BLUE}TEXT-GENERATION-WEBUI SETUP${NC}"
|
||||
echo
|
||||
echo -e " Please ensure you have started your Text-generation-webui Python"
|
||||
echo -e " environment. If you have NOT done this, please run ${L_GREEN}/cmd_linux.sh${NC}"
|
||||
echo -e " in the ${L_GREEN}text-generation-webui${NC} folder and then re-run this script."
|
||||
echo
|
||||
echo " BASE REQUIREMENTS"
|
||||
echo -e " 1) Apply/Re-Apply the requirements for an ${L_GREEN}Text-generation-webui${NC}"
|
||||
echo
|
||||
echo " OPTIONAL"
|
||||
echo " 2) Git Pull the latest AllTalk updates from Github"
|
||||
echo
|
||||
echo " DEEPSPEED"
|
||||
echo " 4) Install DeepSpeed."
|
||||
echo " 5) Uninstall DeepSpeed."
|
||||
echo
|
||||
echo " OTHER"
|
||||
echo " 6) Generate a diagnostics file."
|
||||
echo
|
||||
echo -e " 9)${L_RED} Exit/Quit${NC}"
|
||||
echo
|
||||
read -p " Enter your choice: " webui_option
|
||||
|
||||
case $webui_option in
|
||||
1) install_nvidia_textgen ;;
|
||||
2) tg_gitpull ;;
|
||||
4) install_deepspeed ;;
|
||||
5) uninstall_deepspeed ;;
|
||||
6) generate_diagnostics_textgen ;;
|
||||
9) exit 0 ;;
|
||||
*) echo "Invalid option"; sleep 2 ;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
install_nvidia_textgen() {
|
||||
local requirements_file="system/requirements/requirements_textgen.txt"
|
||||
echo " Installing Requirements from $requirements_file..."
|
||||
if ! pip install -r "$requirements_file"; then
|
||||
echo
|
||||
echo " There was an error pulling from Github."
|
||||
echo " Please check the output for details."
|
||||
read -p " Press any key to return to the menu. " -n 1
|
||||
echo
|
||||
return
|
||||
fi
|
||||
echo
|
||||
echo " Requirements installed successfully."
|
||||
echo
|
||||
echo -e " To install ${L_YELLOW}DeepSpeed${NC} on Linux, there are additional"
|
||||
echo -e " steps required. Please see the Github or documentation on DeepSeed."
|
||||
echo
|
||||
read -p " Press any key to continue. " -n 1
|
||||
echo
|
||||
}
|
||||
|
||||
tg_gitpull() {
|
||||
echo
|
||||
if ! git pull; then
|
||||
echo
|
||||
echo " There was an error installing the requirements."
|
||||
echo " Please check the output for details."
|
||||
echo
|
||||
read -p " Press any key to return to the menu. " -n 1
|
||||
echo
|
||||
return
|
||||
fi
|
||||
echo
|
||||
echo " AllTalk Updated from Github. Please re-apply"
|
||||
echo " the latest requirements file. (Option 1)"
|
||||
echo
|
||||
read -p " Press any key to continue. " -n 1
|
||||
echo
|
||||
}
|
||||
|
||||
# Function to install DeepSpeed
|
||||
install_deepspeed() {
|
||||
clear
|
||||
echo
|
||||
echo -e " ${L_BLUE}DEEPSPEED INSTALLATION REQUIREMENTS${NC}"
|
||||
echo
|
||||
echo -e " - NVIDIA CUDA Toolkit must be installed from your ${L_GREEN}Linux package manager${NC}"
|
||||
echo -e " or ${L_GREEN}https://developer.nvidia.com/cuda-toolkit-archive${NC}"
|
||||
echo -e " - The environment variable ${L_GREEN}CUDA_HOME${NC} must be set in your Python env"
|
||||
echo -e " e.g. export CUDA_HOME=/usr/local/cuda."
|
||||
echo -e " - ${L_GREEN}libaio-dev${NC} must be installed."
|
||||
echo
|
||||
echo -e " See the following link for full instructions:"
|
||||
echo -e " ${L_GREEN}https://github.com/erew123/alltalk_tts?#-deepspeed-installation-options${NC}"
|
||||
echo
|
||||
echo -e " ${L_BLUE}Please ${L_RED}confirm${L_BLUE} that you have completed these steps before continuing"
|
||||
echo -e " with the DeepSpeed installation, or the install ${L_RED}will fail.${NC}"
|
||||
echo
|
||||
read -p " Have you completed all the above steps? (y/n): " confirm
|
||||
|
||||
if [ "$confirm" != "y" ]; then
|
||||
echo -e " ${RED}DeepSpeed installation cannot proceed without completing the prerequisites.${NC}"
|
||||
return
|
||||
fi
|
||||
|
||||
echo -e "\n ${GREEN}Proceeding with DeepSpeed installation...${NC}"
|
||||
pip install deepspeed
|
||||
if [ $? -ne 0 ]; then
|
||||
echo -e " ${RED}There was an error installing DeepSpeed.${NC}"
|
||||
return
|
||||
fi
|
||||
|
||||
echo -e " ${GREEN}DeepSpeed installed successfully.${NC}"
|
||||
read -p " Press any key to continue. " -n 1
|
||||
echo
|
||||
}
|
||||
|
||||
uninstall_deepspeed() {
|
||||
echo "Uninstalling DeepSpeed..."
|
||||
pip uninstall -y deepspeed
|
||||
if [ $? -ne 0 ]; then
|
||||
echo
|
||||
echo " There was an error uninstalling DeepSpeed."
|
||||
echo
|
||||
echo " Press any key to return to the menu."
|
||||
read -n 1
|
||||
return
|
||||
fi
|
||||
echo
|
||||
echo " DeepSpeed uninstalled successfully."
|
||||
echo
|
||||
echo " Press any key to continue."
|
||||
read -n 1
|
||||
}
|
||||
|
||||
generate_diagnostics_textgen() {
|
||||
# Run diagnostics
|
||||
if ! python diagnostics.py; then
|
||||
echo
|
||||
echo " There was an error running diagnostics."
|
||||
echo
|
||||
read -p " Press any key to return to the menu. " -n 1
|
||||
echo
|
||||
return
|
||||
fi
|
||||
echo
|
||||
echo " Diagnostics log file generated successfully."
|
||||
echo " Please see diagnostics.log"
|
||||
echo
|
||||
read -p " Press any key to continue. " -n 1
|
||||
echo
|
||||
}
|
||||
|
||||
# Standalone Menu
|
||||
standalone_menu() {
|
||||
while true; do
|
||||
clear
|
||||
echo
|
||||
echo -e " ${L_BLUE}ALLTALK STANDALONE APPLICATION SETUP${NC}"
|
||||
echo
|
||||
echo " BASE REQUIREMENTS"
|
||||
echo " 1) Install AllTalk as a Standalone Application"
|
||||
echo
|
||||
echo " OPTIONAL"
|
||||
echo " 2) Git Pull the latest AllTalk updates from Github"
|
||||
echo " 3) Re-Apply/Update the requirements file"
|
||||
echo " 4) Delete AllTalk's custom Python environment"
|
||||
echo " 5) Purge the PIP cache"
|
||||
echo
|
||||
echo " DEEPSPEED"
|
||||
echo " 6) DeepSpeed Instructions/Install"
|
||||
echo
|
||||
echo " OTHER"
|
||||
echo " 8) Generate a diagnostics file"
|
||||
echo
|
||||
echo -e " 9)${L_RED} Exit/Quit${NC}"
|
||||
echo
|
||||
read -p " Enter your choice: " standalone_option
|
||||
|
||||
case $standalone_option in
|
||||
1) install_custom_standalone ;;
|
||||
2) gitpull_standalone ;;
|
||||
3) reapply_standalone ;;
|
||||
4) delete_custom_standalone ;;
|
||||
5) pippurge_standalone ;;
|
||||
6) install_deepspeed ;;
|
||||
8) generate_diagnostics_standalone ;;
|
||||
9) exit 0 ;;
|
||||
*) echo "Invalid option"; sleep 2 ;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
|
||||
install_custom_standalone() {
|
||||
cd "$(dirname "${BASH_SOURCE[0]}")"
|
||||
|
||||
if [[ "$(pwd)" =~ " " ]]; then
|
||||
echo "This script relies on Miniconda which can not be silently installed under a path with spaces."
|
||||
exit
|
||||
fi
|
||||
|
||||
# Deactivate existing conda envs as needed to avoid conflicts
|
||||
{ conda deactivate && conda deactivate && conda deactivate; } 2> /dev/null
|
||||
|
||||
OS_ARCH=$(uname -m)
|
||||
case "${OS_ARCH}" in
|
||||
x86_64*) OS_ARCH="x86_64" ;;
|
||||
arm64* | aarch64*) OS_ARCH="aarch64" ;;
|
||||
*) echo "Unknown system architecture: $OS_ARCH! This script runs only on x86_64 or arm64" && exit ;;
|
||||
esac
|
||||
|
||||
# Config
|
||||
INSTALL_DIR="$(pwd)/alltalk_environment"
|
||||
CONDA_ROOT_PREFIX="${INSTALL_DIR}/conda"
|
||||
INSTALL_ENV_DIR="${INSTALL_DIR}/env"
|
||||
MINICONDA_DOWNLOAD_URL="https://repo.anaconda.com/miniconda/Miniconda3-py310_23.3.1-0-Linux-${OS_ARCH}.sh"
|
||||
|
||||
if [ ! -x "${CONDA_ROOT_PREFIX}/bin/conda" ]; then
|
||||
echo "Downloading Miniconda from $MINICONDA_DOWNLOAD_URL to ${INSTALL_DIR}/miniconda_installer.sh"
|
||||
mkdir -p "${INSTALL_DIR}"
|
||||
curl -L "${MINICONDA_DOWNLOAD_URL}" -o "${INSTALL_DIR}/miniconda_installer.sh"
|
||||
chmod +x "${INSTALL_DIR}/miniconda_installer.sh"
|
||||
bash "${INSTALL_DIR}/miniconda_installer.sh" -b -p "${CONDA_ROOT_PREFIX}"
|
||||
echo "Miniconda installed."
|
||||
fi
|
||||
|
||||
if [ ! -d "${INSTALL_ENV_DIR}" ]; then
|
||||
"${CONDA_ROOT_PREFIX}/bin/conda" create -y --prefix "${INSTALL_ENV_DIR}" python=3.11
|
||||
echo "Conda environment created at ${INSTALL_ENV_DIR}."
|
||||
fi
|
||||
|
||||
# Activate the environment and install requirements
|
||||
source "${CONDA_ROOT_PREFIX}/etc/profile.d/conda.sh"
|
||||
conda activate "${INSTALL_ENV_DIR}"
|
||||
echo
|
||||
echo " Downloading and installing PyTorch. This step can take a long time"
|
||||
echo " depending on your internet connection and hard drive speed. Please"
|
||||
echo " be patient."
|
||||
pip install torch>=2.2.1+cu121 torchaudio>=2.2.1+cu121 --upgrade --force-reinstall --extra-index-url https://download.pytorch.org/whl/cu121
|
||||
echo
|
||||
echo " Installing additional requirements."
|
||||
echo
|
||||
pip install -r system/requirements/requirements_standalone.txt
|
||||
# Create start_environment.sh to run AllTalk
|
||||
cat << EOF > start_environment.sh
|
||||
#!/bin/bash
|
||||
cd "$(dirname "${BASH_SOURCE[0]}")"
|
||||
if [[ "$(pwd)" =~ " " ]]; then echo This script relies on Miniconda which can not be silently installed under a path with spaces. && exit; fi
|
||||
# deactivate existing conda envs as needed to avoid conflicts
|
||||
{ conda deactivate && conda deactivate && conda deactivate; } 2> /dev/null
|
||||
# config
|
||||
CONDA_ROOT_PREFIX="$(pwd)/alltalk_environment/conda"
|
||||
INSTALL_ENV_DIR="$(pwd)/alltalk_environment/env"
|
||||
# environment isolation
|
||||
export PYTHONNOUSERSITE=1
|
||||
unset PYTHONPATH
|
||||
unset PYTHONHOME
|
||||
export CUDA_PATH="$INSTALL_ENV_DIR"
|
||||
export CUDA_HOME="$CUDA_PATH"
|
||||
export LD_LIBRARY_PATH=`python3 -c 'import os; import nvidia.cublas.lib; import nvidia.cudnn.lib; print(os.path.dirname(nvidia.cublas.lib.__file__) + ":" + os.path.dirname(nvidia.cudnn.lib.__file__))'`
|
||||
# activate env
|
||||
bash --init-file <(echo "source \"$CONDA_ROOT_PREFIX/etc/profile.d/conda.sh\" && conda activate \"$INSTALL_ENV_DIR\"")
|
||||
EOF
|
||||
# Create start_alltalk.sh to run AllTalk
|
||||
cat << EOF > start_alltalk.sh
|
||||
#!/bin/bash
|
||||
export LD_LIBRARY_PATH=`python3 -c 'import os; import nvidia.cublas.lib; import nvidia.cudnn.lib; print(os.path.dirname(nvidia.cublas.lib.__file__) + ":" + os.path.dirname(nvidia.cudnn.lib.__file__))'`
|
||||
source "${CONDA_ROOT_PREFIX}/etc/profile.d/conda.sh"
|
||||
conda activate "${INSTALL_ENV_DIR}"
|
||||
python script.py
|
||||
EOF
|
||||
# Create start_finetune.sh to run AllTalk
|
||||
cat << EOF > start_finetune.sh
|
||||
#!/bin/bash
|
||||
export TRAINER_TELEMETRY=0
|
||||
export LD_LIBRARY_PATH=`python3 -c 'import os; import nvidia.cublas.lib; import nvidia.cudnn.lib; print(os.path.dirname(nvidia.cublas.lib.__file__) + ":" + os.path.dirname(nvidia.cudnn.lib.__file__))'`
|
||||
source "${CONDA_ROOT_PREFIX}/etc/profile.d/conda.sh"
|
||||
conda activate "${INSTALL_ENV_DIR}"
|
||||
python finetune.py
|
||||
EOF
|
||||
chmod +x start_alltalk.sh
|
||||
chmod +x start_environment.sh
|
||||
chmod +x start_finetune.sh
|
||||
echo
|
||||
echo
|
||||
echo -e " Run ${L_YELLOW}./start_alltalk.sh${NC} to start AllTalk."
|
||||
echo -e " Run ${L_YELLOW}./start_finetune.sh${NC} to start Finetuning."
|
||||
echo -e " Run ${L_YELLOW}./start_environment.sh${NC} to start the AllTalk Python environment."
|
||||
echo
|
||||
echo -e " To install ${L_YELLOW}DeepSpeed${NC} on Linux, there are additional"
|
||||
echo -e " steps required. Please see the Github or documentation on DeepSeed."
|
||||
echo
|
||||
read -p " Press any key to continue. " -n 1
|
||||
}
|
||||
|
||||
delete_custom_standalone() {
|
||||
local env_dir="$PWD/alltalk_environment"
|
||||
# Check if the alltalk_environment directory exists
|
||||
if [ ! -d "$env_dir" ]; then
|
||||
echo " \"$env_dir\" directory does not exist. No need to delete."
|
||||
read -p " Press any key to continue. " -n 1
|
||||
echo
|
||||
return
|
||||
fi
|
||||
# Check if a Conda environment is active and deactivate it
|
||||
if [ -n "$CONDA_PREFIX" ]; then
|
||||
echo " Exiting the Conda environment. You may need to start ./atstart.sh again"
|
||||
conda deactivate
|
||||
fi
|
||||
echo "Deleting \"$env_dir\". Please wait."
|
||||
rm -rf "$env_dir"
|
||||
if [ -d "$env_dir" ]; then
|
||||
echo " Failed to delete \"$env_dir\" folder."
|
||||
echo " Please make sure it is not in use and try again."
|
||||
else
|
||||
echo " Environment \"$env_dir\" deleted successfully."
|
||||
fi
|
||||
read -p " Press any key to continue. " -n 1
|
||||
echo
|
||||
}
|
||||
|
||||
generate_diagnostics_standalone() {
|
||||
local env_dir="$PWD/alltalk_environment"
|
||||
local conda_root_prefix="${env_dir}/conda"
|
||||
local install_env_dir="${env_dir}/env"
|
||||
if [ ! -d "${install_env_dir}" ]; then
|
||||
echo
|
||||
echo " The Conda environment at '${install_env_dir}' does not exist."
|
||||
echo " Please install the environment before proceeding."
|
||||
echo
|
||||
read -p " Press any key to return to the menu. " -n 1
|
||||
echo
|
||||
return
|
||||
fi
|
||||
source "${conda_root_prefix}/etc/profile.d/conda.sh"
|
||||
conda activate "${install_env_dir}"
|
||||
if ! python diagnostics.py; then
|
||||
echo
|
||||
echo " There was an error running diagnostics."
|
||||
echo
|
||||
read -p " Press any key to return to the menu. " -n 1
|
||||
echo
|
||||
return
|
||||
fi
|
||||
echo
|
||||
echo " Diagnostics completed successfully."
|
||||
read -p " Press any key to continue. " -n 1
|
||||
echo
|
||||
}
|
||||
|
||||
gitpull_standalone() {
|
||||
local env_dir="$PWD/alltalk_environment"
|
||||
local conda_root_prefix="${env_dir}/conda"
|
||||
local install_env_dir="${env_dir}/env"
|
||||
if [ ! -d "${install_env_dir}" ]; then
|
||||
echo
|
||||
echo " The Conda environment at '${install_env_dir}' does not exist."
|
||||
echo " Please install the environment before proceeding."
|
||||
echo
|
||||
read -p " Press any key to return to the menu. " -n 1
|
||||
echo
|
||||
return
|
||||
fi
|
||||
source "${conda_root_prefix}/etc/profile.d/conda.sh"
|
||||
conda activate "${install_env_dir}"
|
||||
if ! git pull; then
|
||||
echo
|
||||
echo " There was an error pulling from Github."
|
||||
echo
|
||||
read -p " Press any key to return to the menu. " -n 1
|
||||
echo
|
||||
return
|
||||
fi
|
||||
echo
|
||||
echo " AllTalk Updated from Github. Please re-apply."
|
||||
echo " the latest requirements file. (Option 3)"
|
||||
echo
|
||||
read -p " Press any key to continue. " -n 1
|
||||
echo
|
||||
}
|
||||
|
||||
pippurge_standalone() {
|
||||
if ! pip cache purge; then
|
||||
echo
|
||||
echo " There was an error."
|
||||
echo
|
||||
read -p " Press any key to return to the menu. " -n 1
|
||||
echo
|
||||
return
|
||||
fi
|
||||
echo
|
||||
echo " The PIP cache has been purged."
|
||||
echo
|
||||
read -p " Press any key to continue. " -n 1
|
||||
echo
|
||||
}
|
||||
|
||||
reapply_standalone() {
|
||||
local env_dir="$PWD/alltalk_environment"
|
||||
local conda_root_prefix="${env_dir}/conda"
|
||||
local install_env_dir="${env_dir}/env"
|
||||
if [ ! -d "${install_env_dir}" ]; then
|
||||
echo
|
||||
echo " The Conda environment at '${install_env_dir}' does not exist."
|
||||
echo " Please install the environment before proceeding."
|
||||
echo
|
||||
read -p " Press any key to return to the menu. " -n 1
|
||||
echo
|
||||
return
|
||||
fi
|
||||
source "${conda_root_prefix}/etc/profile.d/conda.sh"
|
||||
conda activate "${install_env_dir}"
|
||||
echo
|
||||
echo " Downloading and installing PyTorch. This step can take a long time"
|
||||
echo " depending on your internet connection and hard drive speed. Please"
|
||||
echo " be patient."
|
||||
pip install torch>=2.2.1+cu121 torchaudio>=2.2.1+cu121 --upgrade --force-reinstall --extra-index-url https://download.pytorch.org/whl/cu121
|
||||
echo
|
||||
echo " Installing additional requirements."
|
||||
echo
|
||||
pip install -r system/requirements/requirements_standalone.txt
|
||||
echo
|
||||
echo " Requirements have been re-applied/updated."
|
||||
echo
|
||||
read -p " Press any key to continue. " -n 1
|
||||
echo
|
||||
}
|
||||
|
||||
|
||||
# Start the main menu
|
||||
main_menu
|
||||
@@ -1 +1,25 @@
|
||||
{"activate": true, "autoplay": true, "branding": "AllTalk ", "narrator_enabled": false, "deepspeed_activate": false, "delete_output_wavs": "Disabled", "ip_address": "127.0.0.1", "language": "English", "low_vram": false, "local_temperature": "0.7", "local_repetition_penalty": "10.0", "tts_model_loaded": true, "tts_model_name": "tts_models/multilingual/multi-dataset/xtts_v2", "narrator_voice": "female_01.wav", "output_folder_wav": "extensions/alltalk_tts/outputs/", "output_folder_wav_standalone": "outputs/", "port_number": "7851", "remove_trailing_dots": false, "show_text": true, "tts_method_api_local": false, "tts_method_api_tts": false, "tts_method_xtts_local": true, "voice": "female_01.wav"}
|
||||
{
|
||||
"activate": true,
|
||||
"autoplay": true,
|
||||
"branding": "AllTalk ",
|
||||
"narrator_enabled": false,
|
||||
"deepspeed_activate": false,
|
||||
"delete_output_wavs": "Disabled",
|
||||
"ip_address": "127.0.0.1",
|
||||
"language": "English",
|
||||
"low_vram": false,
|
||||
"local_temperature": "0.7",
|
||||
"local_repetition_penalty": "10.0",
|
||||
"tts_model_loaded": true,
|
||||
"tts_model_name": "tts_models/multilingual/multi-dataset/xtts_v2",
|
||||
"narrator_voice": "female_01.wav",
|
||||
"output_folder_wav": "extensions/alltalk_tts/outputs/",
|
||||
"output_folder_wav_standalone": "outputs/",
|
||||
"port_number": "7851",
|
||||
"remove_trailing_dots": false,
|
||||
"show_text": true,
|
||||
"tts_method_api_local": false,
|
||||
"tts_method_api_tts": false,
|
||||
"tts_method_xtts_local": true,
|
||||
"voice": "female_01.wav"
|
||||
}
|
||||
@@ -8,12 +8,15 @@ try:
|
||||
import re
|
||||
import sys
|
||||
import glob
|
||||
import site
|
||||
import textwrap
|
||||
import torch
|
||||
import packaging.version
|
||||
import packaging.specifiers
|
||||
from packaging.specifiers import SpecifierSet
|
||||
from packaging.specifiers import SpecifierSet
|
||||
from packaging.version import parse as parse_version
|
||||
from pathlib import Path
|
||||
except ImportError as e:
|
||||
print(f"\033[91mError importing module: {e}\033[0m\n")
|
||||
print("\033[94mPlease ensure you started the Text-generation-webUI Python environment with either\033[0m")
|
||||
@@ -21,6 +24,8 @@ except ImportError as e:
|
||||
print("\033[94mfrom the text-generation-webui directory, and then try running the diagnostics again.\033[0m")
|
||||
exit(1)
|
||||
|
||||
this_dir = Path(__file__).parent
|
||||
|
||||
try:
|
||||
import psutil
|
||||
except ImportError:
|
||||
@@ -29,24 +34,30 @@ except ImportError:
|
||||
import psutil
|
||||
|
||||
def get_requirements_file():
|
||||
requirements_files = glob.glob("requirements*.txt")
|
||||
this_dir = Path(__file__).parent # Assuming 'this_dir' is defined as the script's directory
|
||||
requirements_dir = this_dir / 'system' / 'requirements'
|
||||
requirements_files = list(requirements_dir.glob('requirements*.txt')) # Using pathlib for globbing
|
||||
|
||||
if not requirements_files:
|
||||
print("\033[91mNo requirements files found.\033[0m")
|
||||
return None
|
||||
|
||||
print("\033[94m\nSelect a requirements file to check against (or press Enter for default 'requirements.txt'):\033[0m\n")
|
||||
for i, file in enumerate(requirements_files, start=1):
|
||||
print(f"{i}. {file}")
|
||||
for i, file_path in enumerate(requirements_files, start=1):
|
||||
print(f" {i}. {file_path.name}") # Only print the filename
|
||||
|
||||
choice = input("\nEnter the number of your choice: ")
|
||||
try:
|
||||
choice = int(choice) - 1
|
||||
return requirements_files[choice]
|
||||
return str(requirements_files[choice]) # Return the full path as a string
|
||||
except (ValueError, IndexError):
|
||||
return "requirements.txt"
|
||||
return str(requirements_dir / "requirements.txt") # Return the default path as a string
|
||||
|
||||
# Set up logging with filemode='w'
|
||||
logging.basicConfig(filename='diagnostics.log', filemode='w', level=logging.INFO)
|
||||
logging.basicConfig(filename='diagnostics.log',
|
||||
filemode='w',
|
||||
level=logging.INFO,
|
||||
format='%(message)s') # Custom format
|
||||
|
||||
# Function to get GPU information using subprocess
|
||||
def get_gpu_info():
|
||||
@@ -56,6 +67,22 @@ def get_gpu_info():
|
||||
except FileNotFoundError:
|
||||
return "NVIDIA GPU information not available"
|
||||
|
||||
def get_cpu_info():
|
||||
cpu_info = {
|
||||
'physical_cores': psutil.cpu_count(logical=False),
|
||||
'total_cores': psutil.cpu_count(logical=True),
|
||||
'max_frequency': psutil.cpu_freq().max
|
||||
}
|
||||
return cpu_info
|
||||
|
||||
def get_disk_info():
|
||||
disk_info = []
|
||||
partitions = psutil.disk_partitions()
|
||||
for p in partitions:
|
||||
usage = psutil.disk_usage(p.mountpoint)
|
||||
disk_info.append(f" Drive: {p.device} | Total: {usage.total / (1024 ** 3):.2f} GB | Used: {usage.used / (1024 ** 3):.2f} GB | Free: {usage.free / (1024 ** 3):.2f} GB | Type: {p.fstype}")
|
||||
return disk_info
|
||||
|
||||
# Function to check if a port is in use
|
||||
def is_port_in_use(port):
|
||||
for conn in psutil.net_connections():
|
||||
@@ -73,6 +100,38 @@ def satisfies_wildcard(installed_version, required_version):
|
||||
return True
|
||||
return False
|
||||
|
||||
def test_cuda():
|
||||
cuda_available = torch.cuda.is_available()
|
||||
if cuda_available:
|
||||
try:
|
||||
# Attempt to create a tensor on GPU
|
||||
torch.tensor([1.0, 2.0]).cuda()
|
||||
return "Success - CUDA is available and working."
|
||||
except Exception as e:
|
||||
return f"Fail - CUDA is available but not working. Error: {e}"
|
||||
else:
|
||||
return "Fail - CUDA is not available."
|
||||
|
||||
def find_files_in_path_with_wildcard(pattern):
|
||||
# Get the site-packages directory of the current Python environment
|
||||
site_packages_path = site.getsitepackages()
|
||||
found_paths = []
|
||||
# Adjust the sub-directory based on the operating system
|
||||
sub_directory = "nvidia/cublas"
|
||||
if platform.system() == "Linux":
|
||||
sub_directory = os.path.join(sub_directory, "lib")
|
||||
else:
|
||||
sub_directory = os.path.join(sub_directory, "bin")
|
||||
# Iterate over each site-packages directory (there can be more than one)
|
||||
for directory in site_packages_path:
|
||||
# Construct the search directory path
|
||||
search_directory = os.path.join(directory, sub_directory)
|
||||
# Use glob to find all files matching the pattern in this directory
|
||||
for file_path in glob.glob(os.path.join(search_directory, pattern)):
|
||||
if os.path.isfile(file_path): # Ensure it's a file
|
||||
found_paths.append(file_path)
|
||||
return found_paths
|
||||
|
||||
# Function to log and print system information
|
||||
def log_system_info():
|
||||
# System information
|
||||
@@ -88,6 +147,9 @@ def log_system_info():
|
||||
|
||||
# Torch version
|
||||
torch_version = torch.__version__
|
||||
cuda_test_result = test_cuda()
|
||||
cpu_info = get_cpu_info()
|
||||
disk_info = get_disk_info()
|
||||
|
||||
# System RAM using psutil
|
||||
try:
|
||||
@@ -123,6 +185,10 @@ def log_system_info():
|
||||
search_path = sys.path
|
||||
path_env = os.environ.get('PATH', 'N/A')
|
||||
|
||||
# Check for cublas
|
||||
file_name = 'cublas64_11.*' if platform.system() == "Windows" else 'libcublas.so.11*'
|
||||
found_paths = find_files_in_path_with_wildcard(file_name)
|
||||
|
||||
# Compare with requirements file
|
||||
requirements_file = get_requirements_file()
|
||||
if requirements_file:
|
||||
@@ -146,12 +212,27 @@ def log_system_info():
|
||||
logging.info(f"NOTE {requirements_file} not found. Skipping version checks.")
|
||||
|
||||
# Log and print information
|
||||
logging.info(f"OPERATING SYSTEM:")
|
||||
logging.info(f" OS Version: {os_version}")
|
||||
logging.info(f" Note: Windows 11 will list as build is 10.x.22xxx")
|
||||
logging.info(f"Torch Version: {torch_version}")
|
||||
logging.info(f"\nHARDWARE ENVIRONMENT:")
|
||||
logging.info(f" CPU: Physical Cores: {cpu_info['physical_cores']}, Total Cores: {cpu_info['total_cores']}, Max Frequency: {cpu_info['max_frequency']} MHz")
|
||||
logging.info(f" System RAM: {system_ram}")
|
||||
logging.info(f"CUDA_HOME: {cuda_home}")
|
||||
logging.info(f"\nGPU INFORMATION:{gpu_info}")
|
||||
logging.info("DISK INFORMATION:")
|
||||
for disk in disk_info:
|
||||
logging.info(disk)
|
||||
logging.info("\nNETWORK PORT:")
|
||||
logging.info(f" Port Status: {port_status}")
|
||||
logging.info("\nCUDA:")
|
||||
logging.info(f" CUDA Working: {cuda_test_result}")
|
||||
logging.info(f" CUDA_HOME: {cuda_home}")
|
||||
if found_paths:
|
||||
logging.info(f" Cublas64_11 Path: {', '.join(found_paths)}")
|
||||
else:
|
||||
logging.info(f" Cublas64_11 Path: Not found in any search path directories.")
|
||||
logging.info("\nPYTHON & PYTORCH:")
|
||||
logging.info(f" Torch Version: {torch_version}")
|
||||
logging.info(f" Python Version: {platform.python_version()}")
|
||||
logging.info(f" Python Version Info: {python_version_info}")
|
||||
logging.info(f" Python Executable: {python_executable}")
|
||||
@@ -160,38 +241,43 @@ def log_system_info():
|
||||
logging.info("\nPython Search Path:")
|
||||
for path in search_path:
|
||||
logging.info(f" {path}")
|
||||
logging.info("\nOS PATH Environment Variable:")
|
||||
logging.info("\nOS SEARCHPATH ENVIRONMENT:")
|
||||
for path in path_env.split(';'):
|
||||
logging.info(f" {path}")
|
||||
if required_packages: # Check if the dictionary is not empty
|
||||
logging.info("\nPackage Versions:")
|
||||
logging.info("\nPACKAGE VERSIONS vs REQUIREMENTS FILE:")
|
||||
max_package_length = max(len(package) for package in required_packages.keys())
|
||||
for package_name, (operator, required_version) in required_packages.items():
|
||||
installed_version = installed_packages.get(package_name, 'Not installed')
|
||||
logging.info(f" {package_name.ljust(max_package_length)} Required: {operator} {required_version.ljust(12)} Installed: {installed_version}")
|
||||
logging.info(f"GPU Information:\n{gpu_info}")
|
||||
logging.info("Package Versions:")
|
||||
logging.info("\nPYTHON PACKAGES:")
|
||||
for package, version in package_versions.items():
|
||||
logging.info(f" {package}>= {version}")
|
||||
|
||||
# Print to screen
|
||||
print(f"\n\033[94mOS Version:\033[0m \033[92m{os_version}\033[0m")
|
||||
print(f"\033[94mOS Ver note:\033[0m \033[92m(Windows 11 will say build is 10.x.22xxx)\033[0m")
|
||||
print(f"\033[94mCUDA_HOME:\033[0m \033[92m{cuda_home}\033[0m")
|
||||
print(f"\033[94mSystem RAM:\033[0m \033[92m{system_ram}\033[0m")
|
||||
print(f"\033[94mPort Status:\033[0m \033[92m{port_status}\033[0m")
|
||||
print(f"\033[94mTorch Version:\033[0m \033[92m{torch_version}\033[0m")
|
||||
for disk in disk_info:
|
||||
print(f"\033[94mDisk:\033[0m \033[92m{disk}\033[0m")
|
||||
print(f"\033[94m\nGPU Information:\033[0m {gpu_info}")
|
||||
print(f"\033[94mPort Status:\033[0m \033[92m{port_status}\033[0m\n")
|
||||
if "Fail" in cuda_test_result:
|
||||
print(f"\033[91mCUDA Working:\033[0m \033[91m{cuda_test_result}\033[0m")
|
||||
else:
|
||||
print(f"\033[94mCUDA Working:\033[0m \033[92m{cuda_test_result}\033[0m")
|
||||
print(f"\033[94mCUDA_HOME:\033[0m \033[92m{cuda_home}\033[0m")
|
||||
if found_paths:
|
||||
print(f"\033[94mCublas64_11 Path:\033[0m \033[92m{', '.join(found_paths)}\033[0m")
|
||||
else:
|
||||
print(f"\033[94mCublas64_11 Path:\033[0m \033[91mNot found in any search path directories.\033[0m")
|
||||
print(f"\033[94m\nTorch Version:\033[0m \033[92m{torch_version}\033[0m")
|
||||
print(f"\033[94mPython Version:\033[0m \033[92m{platform.python_version()}\033[0m")
|
||||
print(f"\033[94mPython Version Info:\033[0m \033[92m{python_version_info}\033[0m")
|
||||
print(f"\033[94mPython Executable:\033[0m \033[92m{python_executable}\033[0m")
|
||||
print(f"\033[94mPython Virtual Environment:\033[0m \033[92m{python_virtual_env}\033[0m (Should be N/A when in Text-generation-webui Conda Python environment)")
|
||||
print(f"\033[94mConda Environment:\033[0m \033[92m{conda_env}\033[0m")
|
||||
print(f"\n\033[94mPython Search Path:\033[0m")
|
||||
for path in search_path:
|
||||
print(f" {path}")
|
||||
print(f"\n\033[94mOS Search PATH Environment Variable:\033[0m")
|
||||
for path in path_env.split(';'):
|
||||
print(f" {path}")
|
||||
if required_packages: # Check if the dictionary is not empty
|
||||
print("\033[94m\nRequirements file package comparison:\033[0m")
|
||||
max_package_length = max(len(package) for package in required_packages.keys())
|
||||
@@ -215,6 +301,13 @@ def log_system_info():
|
||||
|
||||
# Print colored output
|
||||
print(f" {package_name.ljust(max_package_length)} Required: {color_required}{operator} {required_version.ljust(12)}\033[0m Installed: {color_installed}{installed_version}\033[0m")
|
||||
|
||||
print("\nOn Nvidia Graphics cards machines, if your \033[92mInstalled\033[0m version of \033[92mTorch\033[0m and \033[92mTorchaudio\033[0m does")
|
||||
print("not have \033[92m+cu118\033[0m (Cuda 11.8) or \033[92m+cu121\033[0m (Cuda 12.1) listed after them, you do not have CUDA")
|
||||
print("installed for Torch or Torchaudio in this Python environment. This will cause you problems")
|
||||
print("with \033[94mAllTalk\033[0m and \033[94mFinetuning.\033[0m You may have to 'pip install' a new version of torch and")
|
||||
print("torchaudio, using '\033[94m--upgrade --force-reinstall\033[0m' with the correct version of PyTorch for\033[0m")
|
||||
print("your Python environment.\033[0m")
|
||||
print("\033[94m\nRequirements file specifier meanings:\033[0m")
|
||||
explanation = textwrap.dedent("""
|
||||
== Exact version != Any version except < Less than
|
||||
@@ -224,9 +317,9 @@ def log_system_info():
|
||||
""")
|
||||
print(explanation.strip())
|
||||
print("")
|
||||
print(f"GPU Information:{gpu_info}")
|
||||
print(f"\033[94mDiagnostic log created:\033[0m \033[92mdiagnostics.log\033[0m")
|
||||
print(f"\033[94mPlease upload the log file with any support ticket.\033[0m")
|
||||
print(f"\033[94mDiagnostic log created:\033[0m \033[92mdiagnostics.log. \033[94mA brief summary of results is displayed above on\033[0m")
|
||||
print(f"\033[94mscreen. Please see the log file for more detail.\033[0m")
|
||||
print(f"\033[94m\nPlease upload the log file with any support ticket.\033[0m")
|
||||
|
||||
if __name__ == "__main__":
|
||||
log_system_info()
|
||||
@@ -0,0 +1,20 @@
|
||||
version: '3.8'
|
||||
services:
|
||||
alltalk-tts:
|
||||
image: erew123/alltalk_tts:cuda
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "7851:7851"
|
||||
volumes:
|
||||
- ./outputs:/app/outputs/
|
||||
- ./models:/app/models/
|
||||
- ./voices:/app/voices/
|
||||
- ./finetune/put-voice-samples-in-here:/app/finetune/put-voice-samples-in-here
|
||||
- ./dockerconfig.json:/app/confignew.json
|
||||
deploy:
|
||||
resources:
|
||||
reservations:
|
||||
devices:
|
||||
- driver: nvidia
|
||||
count: all
|
||||
capabilities: [ gpu ]
|
||||
@@ -0,0 +1,21 @@
|
||||
version: '3.8'
|
||||
services:
|
||||
alltalk-tts:
|
||||
image: alltalk:v1-9c
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "7851:7851"
|
||||
- "7852:7852"
|
||||
volumes:
|
||||
- ./outputs:/app/outputs/
|
||||
- ./models:/app/models/
|
||||
- ./voices:/app/voices/
|
||||
- ./finetune/put-voice-samples-in-here:/app/finetune/put-voice-samples-in-here
|
||||
- ./dockerconfig.json:/app/confignew.json
|
||||
deploy:
|
||||
resources:
|
||||
reservations:
|
||||
devices:
|
||||
- driver: nvidia
|
||||
count: all
|
||||
capabilities: [ gpu ]
|
||||
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"activate": true,
|
||||
"autoplay": true,
|
||||
"branding": "AllTalk ",
|
||||
"narrator_enabled": false,
|
||||
"deepspeed_activate": true,
|
||||
"delete_output_wavs": "Disabled",
|
||||
"ip_address": "127.0.0.1",
|
||||
"language": "English",
|
||||
"low_vram": false,
|
||||
"local_temperature": "0.7",
|
||||
"local_repetition_penalty": "10.0",
|
||||
"tts_model_loaded": true,
|
||||
"tts_model_name": "tts_models/multilingual/multi-dataset/xtts_v2",
|
||||
"narrator_voice": "female_01.wav",
|
||||
"output_folder_wav": "extensions/alltalk_tts/outputs/",
|
||||
"output_folder_wav_standalone": "outputs/",
|
||||
"port_number": "7851",
|
||||
"remove_trailing_dots": false,
|
||||
"show_text": true,
|
||||
"tts_method_api_local": false,
|
||||
"tts_method_api_tts": false,
|
||||
"tts_method_xtts_local": true,
|
||||
"voice": "female_01.wav"
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
import torch
|
||||
import os
|
||||
MODEL_PATH = "best_model.pth"
|
||||
# Check if best_model.pth exists
|
||||
if not os.path.exists(MODEL_PATH):
|
||||
print(f"\nCannot find \033[94m{MODEL_PATH}\033[0m in the current folder.")
|
||||
|
||||
# Check if model.pth exists as an alternative
|
||||
ALTERNATIVE_PATH = "model.pth"
|
||||
if os.path.exists(ALTERNATIVE_PATH):
|
||||
print(f"\nIf your model is currently called \033[93m{ALTERNATIVE_PATH}\033[0m please rename it to \033[94mbest_model.pth\033[0m.")
|
||||
else:
|
||||
print(f"Please put \033[91mbest_model.pth\033[0m in the current folder or rename your model file to \033[94mbest_model.pth\033[0m.")
|
||||
exit(1)
|
||||
# Attempt to load the model
|
||||
try:
|
||||
checkpoint = torch.load(MODEL_PATH, map_location=torch.device("cpu"))
|
||||
except Exception as e:
|
||||
print("Error loading checkpoint:", e)
|
||||
raise
|
||||
del checkpoint["optimizer"]
|
||||
for key in list(checkpoint["model"].keys()):
|
||||
if "dvae" in key:
|
||||
del checkpoint["model"][key]
|
||||
torch.save(checkpoint, "model.pth")
|
||||
print(f"\nYour compacted model is created \033[93mmodel.pth\033[0m.")
|
||||
@@ -0,0 +1,5 @@
|
||||
#!/bin/sh
|
||||
python modeldownload.py
|
||||
uvicorn tts_server:app --host 0.0.0.0 --port 7851 --workers 1 --proxy-headers &
|
||||
sleep 5
|
||||
python script.py
|
||||
@@ -8,6 +8,7 @@
|
||||
"model.pth": "https://huggingface.co/coqui/XTTS-v2/resolve/v2.0.2/model.pth?download=true",
|
||||
"dvae.pth": "https://huggingface.co/coqui/XTTS-v2/resolve/v2.0.2/dvae.pth?download=true",
|
||||
"mel_stats.pth": "https://huggingface.co/coqui/XTTS-v2/resolve/v2.0.2/mel_stats.pth?download=true",
|
||||
"speakers_xtts.pth": "https://huggingface.co/coqui/XTTS-v2/resolve/v2.0.2/speakers_xtts.pth?download=true",
|
||||
"vocab.json": "https://huggingface.co/coqui/XTTS-v2/resolve/v2.0.2/vocab.json?download=true"
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,13 @@
|
||||
import os
|
||||
import sys
|
||||
from pathlib import Path
|
||||
import requests
|
||||
from requests.exceptions import ConnectionError
|
||||
from tqdm import tqdm
|
||||
import importlib.metadata as metadata
|
||||
import json
|
||||
from packaging import version
|
||||
from datetime import datetime
|
||||
|
||||
#################################################################
|
||||
#### LOAD PARAMS FROM confignew.json - REQUIRED FOR BRANDING ####
|
||||
@@ -12,14 +15,12 @@ from packaging import version
|
||||
# STARTUP VARIABLE - Create "this_dir" variable as the current script directory
|
||||
this_dir = Path(__file__).parent.resolve()
|
||||
|
||||
|
||||
# load standard config file in and get settings
|
||||
def load_config(file_path):
|
||||
with open(file_path, "r") as config_file:
|
||||
config = json.load(config_file)
|
||||
return config
|
||||
|
||||
|
||||
config_file_path = this_dir / "confignew.json"
|
||||
params = load_config(config_file_path)
|
||||
|
||||
@@ -37,34 +38,26 @@ if modeldownload_config_file_path.exists():
|
||||
files_to_download = settings.get("files_to_download", {})
|
||||
else:
|
||||
# Default settings if the JSON file doesn't exist or is empty
|
||||
print(
|
||||
f"[{params['branding']}Startup] \033[91mWarning\033[0m modeldownload.json is missing so please re-download it and save it in the coquii_tts main folder."
|
||||
)
|
||||
print(
|
||||
f"[{params['branding']}Startup] \033[91mWarning\033[0m API Local and XTTSv2 Local will error unless this is corrected."
|
||||
)
|
||||
print(f"[{params['branding']}Startup] \033[91mWarning\033[0m modeldownload.json is missing so please re-download it and save it in the coquii_tts main folder.")
|
||||
print(f"[{params['branding']}Startup] \033[91mWarning\033[0m API Local and XTTSv2 Local will error unless this is corrected.")
|
||||
|
||||
# Read the version specifier from requirements_nvidia.txt
|
||||
with open(this_dir / "requirements_nvidia.txt", "r") as req_file:
|
||||
with open(this_dir / "system" / "requirements" / "requirements_standalone.txt", "r") as req_file:
|
||||
requirements = req_file.readlines()
|
||||
|
||||
tts_version_required = None
|
||||
for req in requirements:
|
||||
if req.startswith("TTS>="):
|
||||
tts_version_required = req.strip().split(">=")[1]
|
||||
if req.startswith("TTS=="):
|
||||
tts_version_required = req.strip().split("==")[1]
|
||||
break
|
||||
|
||||
if tts_version_required is None:
|
||||
raise ValueError(
|
||||
f"[{params['branding']}Startup] \033[91mWarning\033[0m Could not find TTS version specifier in requirements_nvidia.txt"
|
||||
)
|
||||
|
||||
raise ValueError(f"[{params['branding']}Startup] \033[91mWarning\033[0m Could not find TTS version specifier in requirements file")
|
||||
|
||||
def create_directory_if_not_exists(directory):
|
||||
if not directory.exists():
|
||||
directory.mkdir(parents=True)
|
||||
|
||||
|
||||
def download_file(url, destination):
|
||||
response = requests.get(url, stream=True)
|
||||
total_size_in_bytes = int(response.headers.get("content-length", 0))
|
||||
@@ -83,63 +76,118 @@ def download_file(url, destination):
|
||||
def check_tts_version():
|
||||
try:
|
||||
tts_version = metadata.version("tts")
|
||||
print(
|
||||
f"[{params['branding']}Startup] TTS version installed: \033[93m"
|
||||
+ tts_version
|
||||
+ "\033[0m"
|
||||
)
|
||||
print(f"[{params['branding']}Startup] \033[92mCurrent TTS Version : \033[93m"+tts_version+"\033[0m")
|
||||
|
||||
if version.parse(tts_version) < version.parse(tts_version_required):
|
||||
print(
|
||||
f"[{params['branding']}Startup] \033[91mWarning\033[0m TTS version is too old. Please upgrade to version \033[93m"
|
||||
+ tts_version_required
|
||||
+ "\033[0m or later.\033[0m"
|
||||
)
|
||||
print(
|
||||
f"[{params['branding']}Startup] \033[91mWarning\033[0m At your terminal/command prompt \033[94mpip install --upgrade tts\033[0m"
|
||||
)
|
||||
print(f"[{params['branding']}Startup] \033[91mWarning\033[0m TTS version is too old. Please upgrade to version \033[93m"+tts_version_required+"\033[0m or later.\033[0m")
|
||||
print(f"[{params['branding']}Startup] \033[91mWarning\033[0m At your terminal/command prompt \033[94mpip install --upgrade tts\033[0m")
|
||||
else:
|
||||
print(f"[{params['branding']}Startup] TTS version is up to date.")
|
||||
print(f"[{params['branding']}Startup] \033[92mCurrent TTS Version is :\033[93m Up to date\033[0m")
|
||||
except metadata.PackageNotFoundError:
|
||||
print(
|
||||
f"[{params['branding']}Startup] \033[91mWarning\033[0m TTS is not installed."
|
||||
)
|
||||
print(f"[{params['branding']}Startup] \033[91mWarning\033[0m TTS is not installed")
|
||||
|
||||
def check_torch_version():
|
||||
import torch
|
||||
pytorch_version = torch.__version__
|
||||
cuda_version = torch.version.cuda
|
||||
major, minor, micro = sys.version_info[:3]
|
||||
python_version = f"{major}.{minor}.{micro}"
|
||||
print(f"[{params['branding']}Startup] \033[92mCurrent Python Version :\033[93m {python_version}\033[0m")
|
||||
print(f"[{params['branding']}Startup] \033[92mCurrent PyTorch Version:\033[93m {pytorch_version}\033[0m")
|
||||
if cuda_version is None:
|
||||
print(f"[{params['branding']}Startup] \033[92mCurrent CUDA Version :\033[91m CUDA is not available\033[0m")
|
||||
else:
|
||||
print(f"[{params['branding']}Startup] \033[92mCurrent CUDA Version :\033[93m {cuda_version}\033[0m")
|
||||
|
||||
def ordinal(n):
|
||||
return "%d%s" % (n, "th" if 4 <= n % 100 <= 20 else {1: "st", 2: "nd", 3: "rd"}.get(n % 10, "th"))
|
||||
|
||||
def format_datetime(iso_str):
|
||||
# Parse the ISO 8601 string to datetime
|
||||
dt = datetime.strptime(iso_str, "%Y-%m-%dT%H:%M:%SZ")
|
||||
# Format the datetime into a more readable string
|
||||
return dt.strftime(f"{ordinal(dt.day)} %B %Y at %H:%M")
|
||||
|
||||
def fetch_latest_commit_sha_and_date(owner, repo):
|
||||
url = f"https://api.github.com/repos/{owner}/{repo}/commits"
|
||||
try:
|
||||
response = requests.get(url)
|
||||
if response.status_code == 200:
|
||||
latest_commit = response.json()[0]
|
||||
latest_commit_sha = latest_commit['sha']
|
||||
latest_commit_date = latest_commit['commit']['committer']['date']
|
||||
return latest_commit_sha, latest_commit_date
|
||||
else:
|
||||
print(f"[{params['branding']}Startup] \033[92m{params['branding']}Github updated :\033[91m Failed to fetch the latest commits due to an unexpected response from GitHub")
|
||||
return None, None
|
||||
except ConnectionError:
|
||||
# This block is executed when a connection error occurs
|
||||
print(f"[{params['branding']}Startup] \033[92m{params['branding']}Github updated :\033[91m Could not reach GitHub to check for updates\033[0m")
|
||||
return None, None
|
||||
|
||||
def read_or_initialize_sha(file_path):
|
||||
if os.path.exists(file_path):
|
||||
with open(file_path, 'r') as file:
|
||||
data = json.load(file)
|
||||
return data.get("last_known_commit_sha")
|
||||
else:
|
||||
# File doesn't exist, fetch the latest SHA and create the file
|
||||
latest_commit_sha = fetch_latest_commit_sha_and_date(github_site, github_repository)
|
||||
if latest_commit_sha:
|
||||
with open(file_path, 'w') as file:
|
||||
json.dump({"last_known_commit_sha": latest_commit_sha}, file)
|
||||
return latest_commit_sha
|
||||
else:
|
||||
# Handle the case where GitHub couldn't be reached
|
||||
return None
|
||||
|
||||
def update_sha_file(file_path, new_sha):
|
||||
with open(file_path, 'w') as file:
|
||||
json.dump({"last_known_commit_sha": new_sha}, file)
|
||||
|
||||
# Check and create directories
|
||||
if str(base_path) == "models":
|
||||
create_directory_if_not_exists(this_dir / base_path / model_path)
|
||||
else:
|
||||
create_directory_if_not_exists(base_path / model_path)
|
||||
print(
|
||||
f"[{params['branding']}Startup] \033[94mInfo\033[0m Custom path set in \033[93mmodeldownload.json\033[0m. Using the following settings:"
|
||||
)
|
||||
print(
|
||||
f"[{params['branding']}Startup] \033[94mInfo\033[0m Base folder Path:\033[93m",
|
||||
base_path,
|
||||
"\033[0m",
|
||||
)
|
||||
print(
|
||||
f"[{params['branding']}Startup] \033[94mInfo\033[0m Model folder Path:\033[93m",
|
||||
model_path,
|
||||
"\033[0m",
|
||||
)
|
||||
print(
|
||||
f"[{params['branding']}Startup] \033[94mInfo\033[0m Full Path:\033[93m",
|
||||
base_path / model_path,
|
||||
"\033[0m",
|
||||
)
|
||||
print(f"[{params['branding']}Startup] \033[94mInfo\033[0m Custom path set in \033[93mmodeldownload.json\033[0m. Using the following settings:")
|
||||
print(f"[{params['branding']}Startup] \033[94mInfo\033[0m Base folder Path:\033[93m",base_path,"\033[0m",)
|
||||
print(f"[{params['branding']}Startup] \033[94mInfo\033[0m Model folder Path:\033[93m",model_path,"\033[0m",)
|
||||
print(f"[{params['branding']}Startup] \033[94mInfo\033[0m Full Path:\033[93m",base_path / model_path,"\033[0m",)
|
||||
|
||||
# Download files if they don't exist
|
||||
print("[" + params["branding"] + "Startup] Checking Model is Downloaded.")
|
||||
print(f"[{params['branding']}Startup] \033[92mModel is available :\033[93m Checking\033[0m")
|
||||
for filename, url in files_to_download.items():
|
||||
if str(base_path) == "models":
|
||||
destination = this_dir / base_path / model_path / filename
|
||||
else:
|
||||
destination = Path(base_path) / model_path / filename
|
||||
|
||||
if not destination.exists():
|
||||
print(f"[{params['branding']}Startup] Downloading " + filename + "...")
|
||||
print(f"[{params['branding']}Startup] \033[92mModel Downloading file : \033[93m" + filename + "\033[0m")
|
||||
download_file(url, destination)
|
||||
print(f"[{params['branding']}Startup] \033[92mModel is available :\033[93m Checked\033[0m")
|
||||
|
||||
github_site = "erew123"
|
||||
github_repository = "alltalk_tts"
|
||||
|
||||
check_torch_version()
|
||||
check_tts_version()
|
||||
# Define the file path based on your directory structure
|
||||
sha_file_path = this_dir / "system" / "config" / "at_github_sha.json"
|
||||
|
||||
# Read or initialize the SHA (adjusted for handling both SHA and date)
|
||||
last_known_commit_sha = read_or_initialize_sha(sha_file_path) # Assuming adjustment for date
|
||||
|
||||
# Assuming you have fetched the latest commit SHA and date
|
||||
latest_commit_sha, latest_commit_date = fetch_latest_commit_sha_and_date(github_site, github_repository)
|
||||
|
||||
formatted_date = format_datetime(latest_commit_date) if latest_commit_date else "an unknown date"
|
||||
|
||||
if latest_commit_sha and latest_commit_sha != last_known_commit_sha:
|
||||
#print(f"There's an update available for alltalk_tts.")
|
||||
print(f"[{params['branding']}Startup] \033[92m{params['branding']}Github updated :\033[93m {formatted_date}\033[0m")
|
||||
# Update the file with the new SHA
|
||||
update_sha_file(sha_file_path, latest_commit_sha)
|
||||
elif latest_commit_sha == last_known_commit_sha:
|
||||
#print(f"Your alltalk_tts software is up to date.")
|
||||
print(f"[{params['branding']}Startup] \033[92m{params['branding']}Github updated :\033[93m {formatted_date}\033[0m")
|
||||
@@ -0,0 +1,22 @@
|
||||
FROM nvidia/cuda:12.1.1-devel-ubuntu22.04
|
||||
ENV HOST 0.0.0.0
|
||||
RUN apt-get update && apt-get upgrade -y \
|
||||
&& apt-get install -y git build-essential portaudio19-dev \
|
||||
python3 python3-pip gcc wget \
|
||||
ocl-icd-opencl-dev opencl-headers clinfo \
|
||||
libclblast-dev libopenblas-dev \
|
||||
&& mkdir -p /etc/OpenCL/vendors && echo "libnvidia-opencl.so.1" > /etc/OpenCL/vendors/nvidia.icd \
|
||||
&& ln -s /usr/bin/python3 /usr/bin/python
|
||||
|
||||
RUN mkdir /app/pip_cache
|
||||
ENV PIP_CACHE_DIR=/app/pip_cache
|
||||
|
||||
WORKDIR /app
|
||||
COPY . .
|
||||
ENV CUDA_DOCKER_ARCH=all
|
||||
RUN pip install --no-cache-dir --no-deps -r system/requirements/requirements_standalone.txt --cache-dir=/app/pip_cache && \
|
||||
pip install --no-cache-dir deepspeed --cache-dir=/app/pip_cache
|
||||
|
||||
EXPOSE 7851
|
||||
RUN chmod +x launch.sh
|
||||
ENTRYPOINT ["sh", "-c", "./launch.sh"]
|
||||
@@ -1,7 +0,0 @@
|
||||
gradio>=3.50.2
|
||||
torch>=2.1.0+cu118
|
||||
torchaudio>=2.1.0+cu118
|
||||
TTS==0.21.3
|
||||
faster-whisper>=0.10.0
|
||||
tqdm>=4.66.0
|
||||
pandas>=1.5.0
|
||||
@@ -1,13 +0,0 @@
|
||||
numpy>=1.22.0
|
||||
soundfile>=0.12.1
|
||||
uvicorn>=0.24.0.post1
|
||||
TTS>=0.21.3
|
||||
torch>=2.1.0+cu118
|
||||
torchaudio>=2.1.0+cu118
|
||||
fastapi>=0.104.1
|
||||
Jinja2>=3.1.2
|
||||
requests>=2.31.0
|
||||
tqdm>=4.66.1
|
||||
importlib-metadata>=4.8.1
|
||||
packaging>=23.2
|
||||
pydantic>=1.10.13
|
||||
@@ -1,13 +0,0 @@
|
||||
numpy>=1.22.0
|
||||
soundfile>=0.12.1
|
||||
uvicorn>=0.24.0.post1
|
||||
TTS>=0.21.3
|
||||
torch>=2.1.0
|
||||
torchaudio>=2.1.0
|
||||
fastapi>=0.104.1
|
||||
Jinja2>=3.1.2
|
||||
requests>=2.31.0
|
||||
tqdm>=4.66.1
|
||||
importlib-metadata>=4.8.1
|
||||
packaging>=23.2
|
||||
pydantic>=1.10.13
|
||||
@@ -1,8 +0,0 @@
|
||||
.SDAP .hires_opts input[type="number"] {
|
||||
width: 6em !important;
|
||||
}
|
||||
|
||||
/* silero_tts preview */
|
||||
.form:has(> #silero_preview_text) {
|
||||
min-width: 75%
|
||||
}
|
||||
|
After Width: | Height: | Size: 97 KiB |
|
After Width: | Height: | Size: 11 KiB |
@@ -89,25 +89,25 @@
|
||||
<h3>AllTalk Startup Settings</h3><br>
|
||||
<form action="/update-settings" method="post">
|
||||
|
||||
<label for="activate" style="color: #33cc33;">Activate TTS:</label>
|
||||
<label for="activate" style="color: #b273fa;">TG-webui Activate TTS:</label>
|
||||
<select id="activate" name="activate" required="">
|
||||
<option {% if data.activate %}selected{% endif %} value="true">True</option>
|
||||
<option {% if not data.activate %}selected{% endif %} value="false">False</option>
|
||||
</select>
|
||||
|
||||
<label for="autoplay" style="color: #33cc33;"> Autoplay TTS output:</label>
|
||||
<label for="autoplay" style="color: #b273fa;"> TG-webui Autoplay TTS:</label>
|
||||
<select id="autoplay" name="autoplay" required="">
|
||||
<option {% if data.autoplay %}selected{% endif %} value="true">True</option>
|
||||
<option {% if not data.autoplay %}selected{% endif %} value="false">False</option>
|
||||
</select>
|
||||
|
||||
<label for="show_text" style="color: #33cc33;"> Show Text on generation:</label>
|
||||
<label for="show_text" style="color: #b273fa;">TG-webui Show Text:</label>
|
||||
<select id="show_text" name="show_text" required="">
|
||||
<option {% if data.show_text %}selected{% endif %} value="true">True</option>
|
||||
<option {% if not data.show_text %}selected{% endif %} value="false">False</option>
|
||||
</select>
|
||||
|
||||
<label for="voice" style="color: #33cc33;"> Default voice:</label>
|
||||
<label for="voice" style="color: #b273fa;"> TG-webui Default voice:</label>
|
||||
<select id="voice" name="voice" required="">
|
||||
{% for file in wav_files %}
|
||||
<option value="{{ file }}" {% if data.voice==file %}selected{% endif %}>{{ file }}</option>
|
||||
@@ -115,7 +115,7 @@
|
||||
</select>
|
||||
|
||||
|
||||
<label for="language" style="color: #33cc33;">Default Language:</label>
|
||||
<label for="language" style="color: #b273fa;">TG-webui Default Language:</label>
|
||||
<select id="language" name="language" required="">
|
||||
<option value="Arabic" {% if data.language=='Arabic' %}selected{% endif %}>Arabic</option>
|
||||
<option value="Chinese" {% if data.language=='Chinese' %}selected{% endif %}>Chinese</option>
|
||||
@@ -124,6 +124,7 @@
|
||||
<option value="English" {% if data.language=='English' %}selected{% endif %}>English</option>
|
||||
<option value="French" {% if data.language=='French' %}selected{% endif %}>French</option>
|
||||
<option value="German" {% if data.language=='German' %}selected{% endif %}>German</option>
|
||||
<option value="Hindi" {% if data.language=='Hindi' %}selected{% endif %}>Hindi</option>
|
||||
<option value="Hungarian" {% if data.language=='Hungarian' %}selected{% endif %}>Hungarian</option>
|
||||
<option value="Italian" {% if data.language=='Italian' %}selected{% endif %}>Italian</option>
|
||||
<option value="Japanese" {% if data.language=='Japanese' %}selected{% endif %}>Japanese</option>
|
||||
@@ -135,20 +136,20 @@
|
||||
<option value="Turkish" {% if data.language=='Turkish' %}selected{% endif %}>Turkish</option>
|
||||
</select>
|
||||
|
||||
<label for="narrator_voice" style="color: #33cc33;"> Narrator voice:</label>
|
||||
<label for="narrator_voice" style="color: #b273fa;"> TG-webui Narrator voice:</label>
|
||||
<select id="narrator_voice" name="narrator_voice" required="">
|
||||
{% for file in wav_files %}
|
||||
<option value="{{ file }}" {% if data.narrator_voice==file %}selected{% endif %}>{{ file }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
|
||||
<label for="remove_trailing_dots" style="color: #33cc33;"> Remove Trailing Dots:</label>
|
||||
<label for="remove_trailing_dots" style="color: #b273fa;">TG-webui Remove Trailing Dots:</label>
|
||||
<select id="remove_trailing_dots" name="remove_trailing_dots" required="">
|
||||
<option {% if data.remove_trailing_dots %}selected{% endif %} value="true">True</option>
|
||||
<option {% if not data.remove_trailing_dots %}selected{% endif %} value="false">False</option>
|
||||
</select>
|
||||
|
||||
<label for="narrator_enabled" style="color: #33cc33;"> Narrator enabled:</label>
|
||||
<label for="narrator_enabled" style="color: #b273fa;"> TG-webui Narrator enabled:</label>
|
||||
<select id="narrator_enabled" name="narrator_enabled" required="">
|
||||
<option {% if data.narrator_enabled %}selected{% endif %} value="true">True</option>
|
||||
<option {% if not data.narrator_enabled %}selected{% endif %} value="false">False</option>
|
||||
|
After Width: | Height: | Size: 216 KiB |
|
After Width: | Height: | Size: 173 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 57 KiB |
|
After Width: | Height: | Size: 59 KiB |
|
After Width: | Height: | Size: 91 KiB |
|
After Width: | Height: | Size: 52 KiB |
@@ -0,0 +1,2 @@
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
{
|
||||
}
|
||||
@@ -6,6 +6,7 @@
|
||||
"English": "en",
|
||||
"French": "fr",
|
||||
"German": "de",
|
||||
"Hindi": "hi",
|
||||
"Hungarian": "hu",
|
||||
"Italian": "it",
|
||||
"Japanese": "ja",
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
@@ -0,0 +1,869 @@
|
||||
import os
|
||||
import re
|
||||
import textwrap
|
||||
from functools import cached_property
|
||||
|
||||
import pypinyin
|
||||
import torch
|
||||
from hangul_romanize import Transliter
|
||||
from hangul_romanize.rule import academic
|
||||
from num2words import num2words
|
||||
from spacy.lang.ar import Arabic
|
||||
from spacy.lang.en import English
|
||||
from spacy.lang.es import Spanish
|
||||
from spacy.lang.ja import Japanese
|
||||
from spacy.lang.zh import Chinese
|
||||
from tokenizers import Tokenizer
|
||||
|
||||
from TTS.tts.layers.xtts.zh_num2words import TextNorm as zh_num2words
|
||||
|
||||
|
||||
def get_spacy_lang(lang):
|
||||
if lang == "zh":
|
||||
return Chinese()
|
||||
elif lang == "ja":
|
||||
return Japanese()
|
||||
elif lang == "ar":
|
||||
return Arabic()
|
||||
elif lang == "es":
|
||||
return Spanish()
|
||||
else:
|
||||
# For most languages, Enlish does the job
|
||||
return English()
|
||||
|
||||
|
||||
def split_sentence(text, lang, text_split_length=250):
|
||||
"""Preprocess the input text"""
|
||||
text_splits = []
|
||||
if text_split_length is not None and len(text) >= text_split_length:
|
||||
text_splits.append("")
|
||||
nlp = get_spacy_lang(lang)
|
||||
nlp.add_pipe("sentencizer")
|
||||
doc = nlp(text)
|
||||
for sentence in doc.sents:
|
||||
if len(text_splits[-1]) + len(str(sentence)) <= text_split_length:
|
||||
# if the last sentence + the current sentence is less than the text_split_length
|
||||
# then add the current sentence to the last sentence
|
||||
text_splits[-1] += " " + str(sentence)
|
||||
text_splits[-1] = text_splits[-1].lstrip()
|
||||
elif len(str(sentence)) > text_split_length:
|
||||
# if the current sentence is greater than the text_split_length
|
||||
for line in textwrap.wrap(
|
||||
str(sentence),
|
||||
width=text_split_length,
|
||||
drop_whitespace=True,
|
||||
break_on_hyphens=False,
|
||||
tabsize=1,
|
||||
):
|
||||
text_splits.append(str(line))
|
||||
else:
|
||||
text_splits.append(str(sentence))
|
||||
|
||||
if len(text_splits) > 1:
|
||||
if text_splits[0] == "":
|
||||
del text_splits[0]
|
||||
else:
|
||||
text_splits = [text.lstrip()]
|
||||
|
||||
return text_splits
|
||||
|
||||
|
||||
_whitespace_re = re.compile(r"\s+")
|
||||
|
||||
# List of (regular expression, replacement) pairs for abbreviations:
|
||||
_abbreviations = {
|
||||
"en": [
|
||||
(re.compile("\\b%s\\." % x[0], re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
("mrs", "misess"),
|
||||
("mr", "mister"),
|
||||
("dr", "doctor"),
|
||||
("st", "saint"),
|
||||
("co", "company"),
|
||||
("jr", "junior"),
|
||||
("maj", "major"),
|
||||
("gen", "general"),
|
||||
("drs", "doctors"),
|
||||
("rev", "reverend"),
|
||||
("lt", "lieutenant"),
|
||||
("hon", "honorable"),
|
||||
("sgt", "sergeant"),
|
||||
("capt", "captain"),
|
||||
("esq", "esquire"),
|
||||
("ltd", "limited"),
|
||||
("col", "colonel"),
|
||||
("ft", "fort"),
|
||||
]
|
||||
],
|
||||
"es": [
|
||||
(re.compile("\\b%s\\." % x[0], re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
("sra", "señora"),
|
||||
("sr", "señor"),
|
||||
("dr", "doctor"),
|
||||
("dra", "doctora"),
|
||||
("st", "santo"),
|
||||
("co", "compañía"),
|
||||
("jr", "junior"),
|
||||
("ltd", "limitada"),
|
||||
]
|
||||
],
|
||||
"fr": [
|
||||
(re.compile("\\b%s\\." % x[0], re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
("mme", "madame"),
|
||||
("mr", "monsieur"),
|
||||
("dr", "docteur"),
|
||||
("st", "saint"),
|
||||
("co", "compagnie"),
|
||||
("jr", "junior"),
|
||||
("ltd", "limitée"),
|
||||
]
|
||||
],
|
||||
"de": [
|
||||
(re.compile("\\b%s\\." % x[0], re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
("fr", "frau"),
|
||||
("dr", "doktor"),
|
||||
("st", "sankt"),
|
||||
("co", "firma"),
|
||||
("jr", "junior"),
|
||||
]
|
||||
],
|
||||
"pt": [
|
||||
(re.compile("\\b%s\\." % x[0], re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
("sra", "senhora"),
|
||||
("sr", "senhor"),
|
||||
("dr", "doutor"),
|
||||
("dra", "doutora"),
|
||||
("st", "santo"),
|
||||
("co", "companhia"),
|
||||
("jr", "júnior"),
|
||||
("ltd", "limitada"),
|
||||
]
|
||||
],
|
||||
"it": [
|
||||
(re.compile("\\b%s\\." % x[0], re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
# ("sig.ra", "signora"),
|
||||
("sig", "signore"),
|
||||
("dr", "dottore"),
|
||||
("st", "santo"),
|
||||
("co", "compagnia"),
|
||||
("jr", "junior"),
|
||||
("ltd", "limitata"),
|
||||
]
|
||||
],
|
||||
"pl": [
|
||||
(re.compile("\\b%s\\." % x[0], re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
("p", "pani"),
|
||||
("m", "pan"),
|
||||
("dr", "doktor"),
|
||||
("sw", "święty"),
|
||||
("jr", "junior"),
|
||||
]
|
||||
],
|
||||
"ar": [
|
||||
(re.compile("\\b%s\\." % x[0], re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
# There are not many common abbreviations in Arabic as in English.
|
||||
]
|
||||
],
|
||||
"zh": [
|
||||
(re.compile("\\b%s\\." % x[0], re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
# Chinese doesn't typically use abbreviations in the same way as Latin-based scripts.
|
||||
]
|
||||
],
|
||||
"cs": [
|
||||
(re.compile("\\b%s\\." % x[0], re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
("dr", "doktor"), # doctor
|
||||
("ing", "inženýr"), # engineer
|
||||
("p", "pan"), # Could also map to pani for woman but no easy way to do it
|
||||
# Other abbreviations would be specialized and not as common.
|
||||
]
|
||||
],
|
||||
"ru": [
|
||||
(re.compile("\\b%s\\b" % x[0], re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
("г-жа", "госпожа"), # Mrs.
|
||||
("г-н", "господин"), # Mr.
|
||||
("д-р", "доктор"), # doctor
|
||||
# Other abbreviations are less common or specialized.
|
||||
]
|
||||
],
|
||||
"nl": [
|
||||
(re.compile("\\b%s\\." % x[0], re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
("dhr", "de heer"), # Mr.
|
||||
("mevr", "mevrouw"), # Mrs.
|
||||
("dr", "dokter"), # doctor
|
||||
("jhr", "jonkheer"), # young lord or nobleman
|
||||
# Dutch uses more abbreviations, but these are the most common ones.
|
||||
]
|
||||
],
|
||||
"tr": [
|
||||
(re.compile("\\b%s\\." % x[0], re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
("b", "bay"), # Mr.
|
||||
("byk", "büyük"), # büyük
|
||||
("dr", "doktor"), # doctor
|
||||
# Add other Turkish abbreviations here if needed.
|
||||
]
|
||||
],
|
||||
"hu": [
|
||||
(re.compile("\\b%s\\." % x[0], re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
("dr", "doktor"), # doctor
|
||||
("b", "bácsi"), # Mr.
|
||||
("nőv", "nővér"), # nurse
|
||||
# Add other Hungarian abbreviations here if needed.
|
||||
]
|
||||
],
|
||||
"ko": [
|
||||
(re.compile("\\b%s\\." % x[0], re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
# Korean doesn't typically use abbreviations in the same way as Latin-based scripts.
|
||||
]
|
||||
],
|
||||
"ja": [
|
||||
(re.compile("\\b%s\\b" % x[0]), x[1])
|
||||
for x in [
|
||||
("氏", "さん"), # Mr.
|
||||
("夫人", "おんなのひと"), # Mrs.
|
||||
("博士", "はかせ"), # Doctor or PhD
|
||||
("株", "株式会社"), # Corporation
|
||||
("有", "有限会社"), # Limited company
|
||||
("大学", "だいがく"), # University
|
||||
("先生", "せんせい"), # Teacher/Professor/Master
|
||||
("君", "くん") # Used at the end of boys' names to express familiarity or affection.
|
||||
]
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
def expand_abbreviations_multilingual(text, lang="en"):
|
||||
for regex, replacement in _abbreviations[lang]:
|
||||
text = re.sub(regex, replacement, text)
|
||||
return text
|
||||
|
||||
|
||||
_symbols_multilingual = {
|
||||
"en": [
|
||||
(re.compile(r"%s" % re.escape(x[0]), re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
("&", " and "),
|
||||
("@", " at "),
|
||||
("%", " percent "),
|
||||
("#", " hash "),
|
||||
("$", " dollar "),
|
||||
("£", " pound "),
|
||||
("°", " degree "),
|
||||
]
|
||||
],
|
||||
"es": [
|
||||
(re.compile(r"%s" % re.escape(x[0]), re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
("&", " y "),
|
||||
("@", " arroba "),
|
||||
("%", " por ciento "),
|
||||
("#", " numeral "),
|
||||
("$", " dolar "),
|
||||
("£", " libra "),
|
||||
("°", " grados "),
|
||||
]
|
||||
],
|
||||
"fr": [
|
||||
(re.compile(r"%s" % re.escape(x[0]), re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
("&", " et "),
|
||||
("@", " arobase "),
|
||||
("%", " pour cent "),
|
||||
("#", " dièse "),
|
||||
("$", " dollar "),
|
||||
("£", " livre "),
|
||||
("°", " degrés "),
|
||||
]
|
||||
],
|
||||
"de": [
|
||||
(re.compile(r"%s" % re.escape(x[0]), re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
("&", " und "),
|
||||
("@", " at "),
|
||||
("%", " prozent "),
|
||||
("#", " raute "),
|
||||
("$", " dollar "),
|
||||
("£", " pfund "),
|
||||
("°", " grad "),
|
||||
]
|
||||
],
|
||||
"pt": [
|
||||
(re.compile(r"%s" % re.escape(x[0]), re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
("&", " e "),
|
||||
("@", " arroba "),
|
||||
("%", " por cento "),
|
||||
("#", " cardinal "),
|
||||
("$", " dólar "),
|
||||
("£", " libra "),
|
||||
("°", " graus "),
|
||||
]
|
||||
],
|
||||
"it": [
|
||||
(re.compile(r"%s" % re.escape(x[0]), re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
("&", " e "),
|
||||
("@", " chiocciola "),
|
||||
("%", " per cento "),
|
||||
("#", " cancelletto "),
|
||||
("$", " dollaro "),
|
||||
("£", " sterlina "),
|
||||
("°", " gradi "),
|
||||
]
|
||||
],
|
||||
"pl": [
|
||||
(re.compile(r"%s" % re.escape(x[0]), re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
("&", " i "),
|
||||
("@", " małpa "),
|
||||
("%", " procent "),
|
||||
("#", " krzyżyk "),
|
||||
("$", " dolar "),
|
||||
("£", " funt "),
|
||||
("°", " stopnie "),
|
||||
]
|
||||
],
|
||||
"ar": [
|
||||
# Arabic
|
||||
(re.compile(r"%s" % re.escape(x[0]), re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
("&", " و "),
|
||||
("@", " على "),
|
||||
("%", " في المئة "),
|
||||
("#", " رقم "),
|
||||
("$", " دولار "),
|
||||
("£", " جنيه "),
|
||||
("°", " درجة "),
|
||||
]
|
||||
],
|
||||
"zh": [
|
||||
# Chinese
|
||||
(re.compile(r"%s" % re.escape(x[0]), re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
("&", " 和 "),
|
||||
("@", " 在 "),
|
||||
("%", " 百分之 "),
|
||||
("#", " 号 "),
|
||||
("$", " 美元 "),
|
||||
("£", " 英镑 "),
|
||||
("°", " 度 "),
|
||||
]
|
||||
],
|
||||
"cs": [
|
||||
# Czech
|
||||
(re.compile(r"%s" % re.escape(x[0]), re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
("&", " a "),
|
||||
("@", " na "),
|
||||
("%", " procento "),
|
||||
("#", " křížek "),
|
||||
("$", " dolar "),
|
||||
("£", " libra "),
|
||||
("°", " stupně "),
|
||||
]
|
||||
],
|
||||
"ru": [
|
||||
# Russian
|
||||
(re.compile(r"%s" % re.escape(x[0]), re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
("&", " и "),
|
||||
("@", " собака "),
|
||||
("%", " процентов "),
|
||||
("#", " номер "),
|
||||
("$", " доллар "),
|
||||
("£", " фунт "),
|
||||
("°", " градус "),
|
||||
]
|
||||
],
|
||||
"nl": [
|
||||
# Dutch
|
||||
(re.compile(r"%s" % re.escape(x[0]), re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
("&", " en "),
|
||||
("@", " bij "),
|
||||
("%", " procent "),
|
||||
("#", " hekje "),
|
||||
("$", " dollar "),
|
||||
("£", " pond "),
|
||||
("°", " graden "),
|
||||
]
|
||||
],
|
||||
"tr": [
|
||||
(re.compile(r"%s" % re.escape(x[0]), re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
("&", " ve "),
|
||||
("@", " at "),
|
||||
("%", " yüzde "),
|
||||
("#", " diyez "),
|
||||
("$", " dolar "),
|
||||
("£", " sterlin "),
|
||||
("°", " derece "),
|
||||
]
|
||||
],
|
||||
"hu": [
|
||||
(re.compile(r"%s" % re.escape(x[0]), re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
("&", " és "),
|
||||
("@", " kukac "),
|
||||
("%", " százalék "),
|
||||
("#", " kettőskereszt "),
|
||||
("$", " dollár "),
|
||||
("£", " font "),
|
||||
("°", " fok "),
|
||||
]
|
||||
],
|
||||
"ko": [
|
||||
# Korean
|
||||
(re.compile(r"%s" % re.escape(x[0]), re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
("&", " 그리고 "),
|
||||
("@", " 에 "),
|
||||
("%", " 퍼센트 "),
|
||||
("#", " 번호 "),
|
||||
("$", " 달러 "),
|
||||
("£", " 파운드 "),
|
||||
("°", " 도 "),
|
||||
]
|
||||
],
|
||||
"ja": [
|
||||
(re.compile(r"%s" % re.escape(x[0])), x[1])
|
||||
for x in [
|
||||
("&", " と "),
|
||||
("@", " アットマーク "),
|
||||
("%", " パーセント "),
|
||||
("#", " ナンバー "),
|
||||
("$", " ドル "),
|
||||
("£", " ポンド "),
|
||||
("°", " 度"),
|
||||
]
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
def expand_symbols_multilingual(text, lang="en"):
|
||||
for regex, replacement in _symbols_multilingual[lang]:
|
||||
text = re.sub(regex, replacement, text)
|
||||
text = text.replace(" ", " ") # Ensure there are no double spaces
|
||||
return text.strip()
|
||||
|
||||
|
||||
_ordinal_re = {
|
||||
"en": re.compile(r"([0-9]+)(st|nd|rd|th)"),
|
||||
"es": re.compile(r"([0-9]+)(º|ª|er|o|a|os|as)"),
|
||||
"fr": re.compile(r"([0-9]+)(º|ª|er|re|e|ème)"),
|
||||
"de": re.compile(r"([0-9]+)(st|nd|rd|th|º|ª|\.(?=\s|$))"),
|
||||
"pt": re.compile(r"([0-9]+)(º|ª|o|a|os|as)"),
|
||||
"it": re.compile(r"([0-9]+)(º|°|ª|o|a|i|e)"),
|
||||
"pl": re.compile(r"([0-9]+)(º|ª|st|nd|rd|th)"),
|
||||
"ar": re.compile(r"([0-9]+)(ون|ين|ث|ر|ى)"),
|
||||
"cs": re.compile(r"([0-9]+)\.(?=\s|$)"), # In Czech, a dot is often used after the number to indicate ordinals.
|
||||
"ru": re.compile(r"([0-9]+)(-й|-я|-е|-ое|-ье|-го)"),
|
||||
"nl": re.compile(r"([0-9]+)(de|ste|e)"),
|
||||
"tr": re.compile(r"([0-9]+)(\.|inci|nci|uncu|üncü|\.)"),
|
||||
"hu": re.compile(r"([0-9]+)(\.|adik|edik|odik|edik|ödik|ödike|ik)"),
|
||||
"ko": re.compile(r"([0-9]+)(번째|번|차|째)"),
|
||||
"ja": re.compile(r"([0-9]+)(番|回|つ|目|等|位)")
|
||||
}
|
||||
_number_re = re.compile(r"[0-9]+")
|
||||
_currency_re = {
|
||||
"USD": re.compile(r"((\$[0-9\.\,]*[0-9]+)|([0-9\.\,]*[0-9]+\$))"),
|
||||
"GBP": re.compile(r"((£[0-9\.\,]*[0-9]+)|([0-9\.\,]*[0-9]+£))"),
|
||||
"EUR": re.compile(r"(([0-9\.\,]*[0-9]+€)|((€[0-9\.\,]*[0-9]+)))"),
|
||||
}
|
||||
|
||||
_comma_number_re = re.compile(r"\b\d{1,3}(,\d{3})*(\.\d+)?\b")
|
||||
_dot_number_re = re.compile(r"\b\d{1,3}(.\d{3})*(\,\d+)?\b")
|
||||
_decimal_number_re = re.compile(r"([0-9]+[.,][0-9]+)")
|
||||
|
||||
|
||||
def _remove_commas(m):
|
||||
text = m.group(0)
|
||||
if "," in text:
|
||||
text = text.replace(",", "")
|
||||
return text
|
||||
|
||||
|
||||
def _remove_dots(m):
|
||||
text = m.group(0)
|
||||
if "." in text:
|
||||
text = text.replace(".", "")
|
||||
return text
|
||||
|
||||
|
||||
def _expand_decimal_point(m, lang="en"):
|
||||
amount = m.group(1).replace(",", ".")
|
||||
return num2words(float(amount), lang=lang if lang != "cs" else "cz")
|
||||
|
||||
|
||||
def _expand_currency(m, lang="en", currency="USD"):
|
||||
amount = float((re.sub(r"[^\d.]", "", m.group(0).replace(",", "."))))
|
||||
full_amount = num2words(amount, to="currency", currency=currency, lang=lang if lang != "cs" else "cz")
|
||||
|
||||
and_equivalents = {
|
||||
"en": ", ",
|
||||
"es": " con ",
|
||||
"fr": " et ",
|
||||
"de": " und ",
|
||||
"pt": " e ",
|
||||
"it": " e ",
|
||||
"pl": ", ",
|
||||
"cs": ", ",
|
||||
"ru": ", ",
|
||||
"nl": ", ",
|
||||
"ar": ", ",
|
||||
"tr": ", ",
|
||||
"hu": ", ",
|
||||
"ko": ", ",
|
||||
}
|
||||
|
||||
if amount.is_integer():
|
||||
last_and = full_amount.rfind(and_equivalents[lang])
|
||||
if last_and != -1:
|
||||
full_amount = full_amount[:last_and]
|
||||
|
||||
return full_amount
|
||||
|
||||
|
||||
def _expand_ordinal(m, lang="en"):
|
||||
return num2words(int(m.group(1)), ordinal=True, lang=lang if lang != "cs" else "cz")
|
||||
|
||||
|
||||
def _expand_number(m, lang="en"):
|
||||
return num2words(int(m.group(0)), lang=lang if lang != "cs" else "cz")
|
||||
|
||||
|
||||
def expand_numbers_multilingual(text, lang="en"):
|
||||
if lang == "zh":
|
||||
text = zh_num2words()(text)
|
||||
else:
|
||||
if lang in ["en", "ru"]:
|
||||
text = re.sub(_comma_number_re, _remove_commas, text)
|
||||
else:
|
||||
text = re.sub(_dot_number_re, _remove_dots, text)
|
||||
try:
|
||||
text = re.sub(_currency_re["GBP"], lambda m: _expand_currency(m, lang, "GBP"), text)
|
||||
text = re.sub(_currency_re["USD"], lambda m: _expand_currency(m, lang, "USD"), text)
|
||||
text = re.sub(_currency_re["EUR"], lambda m: _expand_currency(m, lang, "EUR"), text)
|
||||
except:
|
||||
pass
|
||||
if lang != "tr":
|
||||
text = re.sub(_decimal_number_re, lambda m: _expand_decimal_point(m, lang), text)
|
||||
text = re.sub(_ordinal_re[lang], lambda m: _expand_ordinal(m, lang), text)
|
||||
text = re.sub(_number_re, lambda m: _expand_number(m, lang), text)
|
||||
return text
|
||||
|
||||
|
||||
def lowercase(text):
|
||||
return text.lower()
|
||||
|
||||
|
||||
def collapse_whitespace(text):
|
||||
return re.sub(_whitespace_re, " ", text)
|
||||
|
||||
|
||||
def multilingual_cleaners(text, lang):
|
||||
text = text.replace('"', "")
|
||||
if lang == "tr":
|
||||
text = text.replace("İ", "i")
|
||||
text = text.replace("Ö", "ö")
|
||||
text = text.replace("Ü", "ü")
|
||||
text = lowercase(text)
|
||||
text = expand_numbers_multilingual(text, lang)
|
||||
text = expand_abbreviations_multilingual(text, lang)
|
||||
text = expand_symbols_multilingual(text, lang=lang)
|
||||
text = collapse_whitespace(text)
|
||||
return text
|
||||
|
||||
|
||||
def basic_cleaners(text):
|
||||
"""Basic pipeline that lowercases and collapses whitespace without transliteration."""
|
||||
text = lowercase(text)
|
||||
text = collapse_whitespace(text)
|
||||
return text
|
||||
|
||||
|
||||
def chinese_transliterate(text):
|
||||
return "".join(
|
||||
[p[0] for p in pypinyin.pinyin(text, style=pypinyin.Style.TONE3, heteronym=False, neutral_tone_with_five=True)]
|
||||
)
|
||||
|
||||
|
||||
def japanese_cleaners(text, katsu):
|
||||
text = katsu.romaji(text)
|
||||
text = lowercase(text)
|
||||
return text
|
||||
|
||||
|
||||
def korean_transliterate(text):
|
||||
r = Transliter(academic)
|
||||
return r.translit(text)
|
||||
|
||||
|
||||
DEFAULT_VOCAB_FILE = os.path.join(os.path.dirname(os.path.realpath(__file__)), "../data/tokenizer.json")
|
||||
|
||||
|
||||
class VoiceBpeTokenizer:
|
||||
def __init__(self, vocab_file=None):
|
||||
self.tokenizer = None
|
||||
if vocab_file is not None:
|
||||
self.tokenizer = Tokenizer.from_file(vocab_file)
|
||||
self.char_limits = {
|
||||
"en": 250,
|
||||
"de": 253,
|
||||
"fr": 273,
|
||||
"es": 239,
|
||||
"it": 213,
|
||||
"pt": 203,
|
||||
"pl": 224,
|
||||
"zh": 82,
|
||||
"ar": 166,
|
||||
"cs": 186,
|
||||
"ru": 182,
|
||||
"nl": 251,
|
||||
"tr": 226,
|
||||
"ja": 71,
|
||||
"hu": 224,
|
||||
"ko": 95,
|
||||
}
|
||||
|
||||
@cached_property
|
||||
def katsu(self):
|
||||
import cutlet
|
||||
|
||||
return cutlet.Cutlet()
|
||||
|
||||
def check_input_length(self, txt, lang):
|
||||
lang = lang.split("-")[0] # remove the region
|
||||
limit = self.char_limits.get(lang, 250)
|
||||
if len(txt) > limit:
|
||||
print(
|
||||
f"[!] Warning: The text length exceeds the character limit of {limit} for language '{lang}', this might cause truncated audio."
|
||||
)
|
||||
|
||||
def preprocess_text(self, txt, lang):
|
||||
if lang in {"ar", "cs", "de", "en", "es", "fr", "hu", "it", "nl", "pl", "pt", "ru", "tr", "zh", "ko"}:
|
||||
txt = multilingual_cleaners(txt, lang)
|
||||
if lang == "zh":
|
||||
txt = chinese_transliterate(txt)
|
||||
if lang == "ko":
|
||||
txt = korean_transliterate(txt)
|
||||
elif lang == "ja":
|
||||
txt = japanese_cleaners(txt, self.katsu)
|
||||
elif lang == "hi":
|
||||
# @manmay will implement this
|
||||
txt = basic_cleaners(txt)
|
||||
else:
|
||||
raise NotImplementedError(f"Language '{lang}' is not supported.")
|
||||
return txt
|
||||
|
||||
def encode(self, txt, lang):
|
||||
lang = lang.split("-")[0] # remove the region
|
||||
self.check_input_length(txt, lang)
|
||||
txt = self.preprocess_text(txt, lang)
|
||||
lang = "zh-cn" if lang == "zh" else lang
|
||||
txt = f"[{lang}]{txt}"
|
||||
txt = txt.replace(" ", "[SPACE]")
|
||||
return self.tokenizer.encode(txt).ids
|
||||
|
||||
def decode(self, seq):
|
||||
if isinstance(seq, torch.Tensor):
|
||||
seq = seq.cpu().numpy()
|
||||
txt = self.tokenizer.decode(seq, skip_special_tokens=False).replace(" ", "")
|
||||
txt = txt.replace("[SPACE]", " ")
|
||||
txt = txt.replace("[STOP]", "")
|
||||
txt = txt.replace("[UNK]", "")
|
||||
return txt
|
||||
|
||||
def __len__(self):
|
||||
return self.tokenizer.get_vocab_size()
|
||||
|
||||
def get_number_tokens(self):
|
||||
return max(self.tokenizer.get_vocab().values()) + 1
|
||||
|
||||
|
||||
def test_expand_numbers_multilingual():
|
||||
test_cases = [
|
||||
# English
|
||||
("In 12.5 seconds.", "In twelve point five seconds.", "en"),
|
||||
("There were 50 soldiers.", "There were fifty soldiers.", "en"),
|
||||
("This is a 1st test", "This is a first test", "en"),
|
||||
("That will be $20 sir.", "That will be twenty dollars sir.", "en"),
|
||||
("That will be 20€ sir.", "That will be twenty euro sir.", "en"),
|
||||
("That will be 20.15€ sir.", "That will be twenty euro, fifteen cents sir.", "en"),
|
||||
("That's 100,000.5.", "That's one hundred thousand point five.", "en"),
|
||||
# French
|
||||
("En 12,5 secondes.", "En douze virgule cinq secondes.", "fr"),
|
||||
("Il y avait 50 soldats.", "Il y avait cinquante soldats.", "fr"),
|
||||
("Ceci est un 1er test", "Ceci est un premier test", "fr"),
|
||||
("Cela vous fera $20 monsieur.", "Cela vous fera vingt dollars monsieur.", "fr"),
|
||||
("Cela vous fera 20€ monsieur.", "Cela vous fera vingt euros monsieur.", "fr"),
|
||||
("Cela vous fera 20,15€ monsieur.", "Cela vous fera vingt euros et quinze centimes monsieur.", "fr"),
|
||||
("Ce sera 100.000,5.", "Ce sera cent mille virgule cinq.", "fr"),
|
||||
# German
|
||||
("In 12,5 Sekunden.", "In zwölf Komma fünf Sekunden.", "de"),
|
||||
("Es gab 50 Soldaten.", "Es gab fünfzig Soldaten.", "de"),
|
||||
("Dies ist ein 1. Test", "Dies ist ein erste Test", "de"), # Issue with gender
|
||||
("Das macht $20 Herr.", "Das macht zwanzig Dollar Herr.", "de"),
|
||||
("Das macht 20€ Herr.", "Das macht zwanzig Euro Herr.", "de"),
|
||||
("Das macht 20,15€ Herr.", "Das macht zwanzig Euro und fünfzehn Cent Herr.", "de"),
|
||||
# Spanish
|
||||
("En 12,5 segundos.", "En doce punto cinco segundos.", "es"),
|
||||
("Había 50 soldados.", "Había cincuenta soldados.", "es"),
|
||||
("Este es un 1er test", "Este es un primero test", "es"),
|
||||
("Eso le costará $20 señor.", "Eso le costará veinte dólares señor.", "es"),
|
||||
("Eso le costará 20€ señor.", "Eso le costará veinte euros señor.", "es"),
|
||||
("Eso le costará 20,15€ señor.", "Eso le costará veinte euros con quince céntimos señor.", "es"),
|
||||
# Italian
|
||||
("In 12,5 secondi.", "In dodici virgola cinque secondi.", "it"),
|
||||
("C'erano 50 soldati.", "C'erano cinquanta soldati.", "it"),
|
||||
("Questo è un 1° test", "Questo è un primo test", "it"),
|
||||
("Ti costerà $20 signore.", "Ti costerà venti dollari signore.", "it"),
|
||||
("Ti costerà 20€ signore.", "Ti costerà venti euro signore.", "it"),
|
||||
("Ti costerà 20,15€ signore.", "Ti costerà venti euro e quindici centesimi signore.", "it"),
|
||||
# Portuguese
|
||||
("Em 12,5 segundos.", "Em doze vírgula cinco segundos.", "pt"),
|
||||
("Havia 50 soldados.", "Havia cinquenta soldados.", "pt"),
|
||||
("Este é um 1º teste", "Este é um primeiro teste", "pt"),
|
||||
("Isso custará $20 senhor.", "Isso custará vinte dólares senhor.", "pt"),
|
||||
("Isso custará 20€ senhor.", "Isso custará vinte euros senhor.", "pt"),
|
||||
(
|
||||
"Isso custará 20,15€ senhor.",
|
||||
"Isso custará vinte euros e quinze cêntimos senhor.",
|
||||
"pt",
|
||||
), # "cêntimos" should be "centavos" num2words issue
|
||||
# Polish
|
||||
("W 12,5 sekundy.", "W dwanaście przecinek pięć sekundy.", "pl"),
|
||||
("Było 50 żołnierzy.", "Było pięćdziesiąt żołnierzy.", "pl"),
|
||||
("To będzie kosztować 20€ panie.", "To będzie kosztować dwadzieścia euro panie.", "pl"),
|
||||
("To będzie kosztować 20,15€ panie.", "To będzie kosztować dwadzieścia euro, piętnaście centów panie.", "pl"),
|
||||
# Arabic
|
||||
("في الـ 12,5 ثانية.", "في الـ اثنا عشر , خمسون ثانية.", "ar"),
|
||||
("كان هناك 50 جنديًا.", "كان هناك خمسون جنديًا.", "ar"),
|
||||
# ("ستكون النتيجة $20 يا سيد.", 'ستكون النتيجة عشرون دولار يا سيد.', 'ar'), # $ and € are mising from num2words
|
||||
# ("ستكون النتيجة 20€ يا سيد.", 'ستكون النتيجة عشرون يورو يا سيد.', 'ar'),
|
||||
# Czech
|
||||
("Za 12,5 vteřiny.", "Za dvanáct celá pět vteřiny.", "cs"),
|
||||
("Bylo tam 50 vojáků.", "Bylo tam padesát vojáků.", "cs"),
|
||||
("To bude stát 20€ pane.", "To bude stát dvacet euro pane.", "cs"),
|
||||
("To bude 20.15€ pane.", "To bude dvacet euro, patnáct centů pane.", "cs"),
|
||||
# Russian
|
||||
("Через 12.5 секунды.", "Через двенадцать запятая пять секунды.", "ru"),
|
||||
("Там было 50 солдат.", "Там было пятьдесят солдат.", "ru"),
|
||||
("Это будет 20.15€ сэр.", "Это будет двадцать евро, пятнадцать центов сэр.", "ru"),
|
||||
("Это будет стоить 20€ господин.", "Это будет стоить двадцать евро господин.", "ru"),
|
||||
# Dutch
|
||||
("In 12,5 seconden.", "In twaalf komma vijf seconden.", "nl"),
|
||||
("Er waren 50 soldaten.", "Er waren vijftig soldaten.", "nl"),
|
||||
("Dat wordt dan $20 meneer.", "Dat wordt dan twintig dollar meneer.", "nl"),
|
||||
("Dat wordt dan 20€ meneer.", "Dat wordt dan twintig euro meneer.", "nl"),
|
||||
# Chinese (Simplified)
|
||||
("在12.5秒内", "在十二点五秒内", "zh"),
|
||||
("有50名士兵", "有五十名士兵", "zh"),
|
||||
# ("那将是$20先生", '那将是二十美元先生', 'zh'), currency doesn't work
|
||||
# ("那将是20€先生", '那将是二十欧元先生', 'zh'),
|
||||
# Turkish
|
||||
# ("12,5 saniye içinde.", 'On iki virgül beş saniye içinde.', 'tr'), # decimal doesn't work for TR
|
||||
("50 asker vardı.", "elli asker vardı.", "tr"),
|
||||
("Bu 1. test", "Bu birinci test", "tr"),
|
||||
# ("Bu 100.000,5.", 'Bu yüz bin virgül beş.', 'tr'),
|
||||
# Hungarian
|
||||
("12,5 másodperc alatt.", "tizenkettő egész öt tized másodperc alatt.", "hu"),
|
||||
("50 katona volt.", "ötven katona volt.", "hu"),
|
||||
("Ez az 1. teszt", "Ez az első teszt", "hu"),
|
||||
# Korean
|
||||
("12.5 초 안에.", "십이 점 다섯 초 안에.", "ko"),
|
||||
("50 명의 병사가 있었다.", "오십 명의 병사가 있었다.", "ko"),
|
||||
("이것은 1 번째 테스트입니다", "이것은 첫 번째 테스트입니다", "ko"),
|
||||
]
|
||||
for a, b, lang in test_cases:
|
||||
out = expand_numbers_multilingual(a, lang=lang)
|
||||
assert out == b, f"'{out}' vs '{b}'"
|
||||
|
||||
|
||||
def test_abbreviations_multilingual():
|
||||
test_cases = [
|
||||
# English
|
||||
("Hello Mr. Smith.", "Hello mister Smith.", "en"),
|
||||
("Dr. Jones is here.", "doctor Jones is here.", "en"),
|
||||
# Spanish
|
||||
("Hola Sr. Garcia.", "Hola señor Garcia.", "es"),
|
||||
("La Dra. Martinez es muy buena.", "La doctora Martinez es muy buena.", "es"),
|
||||
# French
|
||||
("Bonjour Mr. Dupond.", "Bonjour monsieur Dupond.", "fr"),
|
||||
("Mme. Moreau est absente aujourd'hui.", "madame Moreau est absente aujourd'hui.", "fr"),
|
||||
# German
|
||||
("Frau Dr. Müller ist sehr klug.", "Frau doktor Müller ist sehr klug.", "de"),
|
||||
# Portuguese
|
||||
("Olá Sr. Silva.", "Olá senhor Silva.", "pt"),
|
||||
("Dra. Costa, você está disponível?", "doutora Costa, você está disponível?", "pt"),
|
||||
# Italian
|
||||
("Buongiorno, Sig. Rossi.", "Buongiorno, signore Rossi.", "it"),
|
||||
# ("Sig.ra Bianchi, posso aiutarti?", 'signora Bianchi, posso aiutarti?', 'it'), # Issue with matching that pattern
|
||||
# Polish
|
||||
("Dzień dobry, P. Kowalski.", "Dzień dobry, pani Kowalski.", "pl"),
|
||||
("M. Nowak, czy mogę zadać pytanie?", "pan Nowak, czy mogę zadać pytanie?", "pl"),
|
||||
# Czech
|
||||
("P. Novák", "pan Novák", "cs"),
|
||||
("Dr. Vojtěch", "doktor Vojtěch", "cs"),
|
||||
# Dutch
|
||||
("Dhr. Jansen", "de heer Jansen", "nl"),
|
||||
("Mevr. de Vries", "mevrouw de Vries", "nl"),
|
||||
# Russian
|
||||
("Здравствуйте Г-н Иванов.", "Здравствуйте господин Иванов.", "ru"),
|
||||
("Д-р Смирнов здесь, чтобы увидеть вас.", "доктор Смирнов здесь, чтобы увидеть вас.", "ru"),
|
||||
# Turkish
|
||||
("Merhaba B. Yılmaz.", "Merhaba bay Yılmaz.", "tr"),
|
||||
("Dr. Ayşe burada.", "doktor Ayşe burada.", "tr"),
|
||||
# Hungarian
|
||||
("Dr. Szabó itt van.", "doktor Szabó itt van.", "hu"),
|
||||
]
|
||||
|
||||
for a, b, lang in test_cases:
|
||||
out = expand_abbreviations_multilingual(a, lang=lang)
|
||||
assert out == b, f"'{out}' vs '{b}'"
|
||||
|
||||
|
||||
def test_symbols_multilingual():
|
||||
test_cases = [
|
||||
("I have 14% battery", "I have 14 percent battery", "en"),
|
||||
("Te veo @ la fiesta", "Te veo arroba la fiesta", "es"),
|
||||
("J'ai 14° de fièvre", "J'ai 14 degrés de fièvre", "fr"),
|
||||
("Die Rechnung beträgt £ 20", "Die Rechnung beträgt pfund 20", "de"),
|
||||
("O meu email é ana&joao@gmail.com", "O meu email é ana e joao arroba gmail.com", "pt"),
|
||||
("linguaggio di programmazione C#", "linguaggio di programmazione C cancelletto", "it"),
|
||||
("Moja temperatura to 36.6°", "Moja temperatura to 36.6 stopnie", "pl"),
|
||||
("Mám 14% baterie", "Mám 14 procento baterie", "cs"),
|
||||
("Těším se na tebe @ party", "Těším se na tebe na party", "cs"),
|
||||
("У меня 14% заряда", "У меня 14 процентов заряда", "ru"),
|
||||
("Я буду @ дома", "Я буду собака дома", "ru"),
|
||||
("Ik heb 14% batterij", "Ik heb 14 procent batterij", "nl"),
|
||||
("Ik zie je @ het feest", "Ik zie je bij het feest", "nl"),
|
||||
("لدي 14% في البطارية", "لدي 14 في المئة في البطارية", "ar"),
|
||||
("我的电量为 14%", "我的电量为 14 百分之", "zh"),
|
||||
("Pilim %14 dolu.", "Pilim yüzde 14 dolu.", "tr"),
|
||||
("Az akkumulátorom töltöttsége 14%", "Az akkumulátorom töltöttsége 14 százalék", "hu"),
|
||||
("배터리 잔량이 14%입니다.", "배터리 잔량이 14 퍼센트입니다.", "ko"),
|
||||
]
|
||||
|
||||
for a, b, lang in test_cases:
|
||||
out = expand_symbols_multilingual(a, lang=lang)
|
||||
assert out == b, f"'{out}' vs '{b}'"
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_expand_numbers_multilingual()
|
||||
test_abbreviations_multilingual()
|
||||
test_symbols_multilingual()
|
||||
@@ -0,0 +1,173 @@
|
||||
absl-py==2.1.0
|
||||
aiofiles==23.2.1
|
||||
aiohttp==3.9.3
|
||||
aiosignal==1.3.1
|
||||
altair==5.2.0
|
||||
annotated-types==0.6.0
|
||||
anyascii==0.3.2
|
||||
anyio==4.3.0
|
||||
attrs==23.2.0
|
||||
audioread==3.0.1
|
||||
av==11.0.0
|
||||
Babel==2.14.0
|
||||
bangla==0.0.2
|
||||
blinker==1.7.0
|
||||
blis==0.7.11
|
||||
bnnumerizer==0.0.2
|
||||
bnunicodenormalizer==0.1.6
|
||||
catalogue==2.0.10
|
||||
certifi==2024.2.2
|
||||
cffi==1.16.0
|
||||
charset-normalizer==3.3.2
|
||||
click==8.1.7
|
||||
cloudpathlib==0.16.0
|
||||
colorama==0.4.6
|
||||
coloredlogs==15.0.1
|
||||
confection==0.1.4
|
||||
contourpy==1.2.0
|
||||
coqpit==0.0.17
|
||||
ctranslate2==4.1.0
|
||||
cutlet==0.4.0
|
||||
cycler==0.12.1
|
||||
cymem==2.0.8
|
||||
Cython==3.0.9
|
||||
dateparser==1.1.8
|
||||
decorator==5.1.1
|
||||
docopt==0.6.2
|
||||
einops==0.7.0
|
||||
encodec==0.1.1
|
||||
exceptiongroup
|
||||
fastapi==0.110.0
|
||||
faster-whisper==1.0.1
|
||||
ffmpy==0.3.2
|
||||
filelock==3.13.3
|
||||
Flask==3.0.2
|
||||
flatbuffers==24.3.25
|
||||
fonttools==4.50.0
|
||||
frozenlist==1.4.1
|
||||
fsspec==2024.3.1
|
||||
fugashi==1.3.1
|
||||
fuzzywuzzy>=0.18.0
|
||||
g2pkk==0.1.2
|
||||
gradio==3.50.2
|
||||
gradio_client==0.6.1
|
||||
grpcio==1.62.1
|
||||
gruut==2.2.3
|
||||
gruut-ipa==0.13.0
|
||||
gruut-lang-de==2.0.0
|
||||
gruut-lang-en==2.0.0
|
||||
gruut-lang-es==2.0.0
|
||||
gruut-lang-fr==2.0.2
|
||||
h11==0.14.0
|
||||
hangul-romanize==0.1.0
|
||||
httpcore==1.0.4
|
||||
httpx==0.27.0
|
||||
huggingface-hub==0.22.1
|
||||
humanfriendly==10.0
|
||||
idna==3.6
|
||||
importlib_metadata==7.1.0
|
||||
importlib_resources==6.4.0
|
||||
inflect==7.0.0
|
||||
itsdangerous==2.1.2
|
||||
jaconv==0.3.4
|
||||
jamo==0.4.1
|
||||
jieba==0.42.1
|
||||
Jinja2==3.1.3
|
||||
joblib==1.3.2
|
||||
jsonlines==1.2.0
|
||||
jsonschema==4.21.1
|
||||
jsonschema-specifications==2023.12.1
|
||||
kiwisolver==1.4.5
|
||||
langcodes==3.3.0
|
||||
lazy_loader==0.3
|
||||
librosa==0.10.1
|
||||
llvmlite==0.42.0
|
||||
Markdown==3.6
|
||||
MarkupSafe==2.1.5
|
||||
matplotlib==3.8.3
|
||||
mojimoji==0.0.13
|
||||
mpmath==1.3.0
|
||||
msgpack==1.0.8
|
||||
multidict==6.0.5
|
||||
murmurhash==1.0.10
|
||||
networkx==2.8.8
|
||||
nltk==3.8.1
|
||||
num2words==0.5.13
|
||||
numba==0.59.1
|
||||
numpy==1.26.4
|
||||
nvidia-cublas-cu11>=11.11.3.6
|
||||
nvidia-cudnn-cu11>=9.0.0.312
|
||||
onnxruntime==1.17.1
|
||||
orjson==3.9.15
|
||||
packaging==24.0
|
||||
pandas==1.5.3
|
||||
pillow==10.2.0
|
||||
platformdirs==4.2.0
|
||||
pooch==1.8.1
|
||||
preshed==3.0.9
|
||||
protobuf==5.26.0
|
||||
psutil==5.9.8
|
||||
pycparser==2.21
|
||||
pydantic==2.6.4
|
||||
pydantic_core==2.16.3
|
||||
pydub==0.25.1
|
||||
pynndescent==0.5.11
|
||||
pyparsing==3.1.2
|
||||
pypinyin==0.51.0
|
||||
pyreadline3==3.4.1
|
||||
pysbd==0.3.4
|
||||
python-crfsuite==0.9.10
|
||||
python-dateutil==2.9.0.post0
|
||||
python-Levenshtein>=0.25.0
|
||||
python-multipart==0.0.9
|
||||
pytz==2024.1
|
||||
PyYAML==6.0.1
|
||||
referencing==0.34.0
|
||||
regex==2023.12.25
|
||||
requests==2.31.0
|
||||
rpds-py==0.18.0
|
||||
safetensors==0.4.2
|
||||
scikit-learn==1.4.1.post1
|
||||
scipy==1.12.0
|
||||
semantic-version==2.10.0
|
||||
six==1.16.0
|
||||
smart-open==6.4.0
|
||||
sniffio==1.3.1
|
||||
sounddevice==0.4.6
|
||||
soundfile==0.12.1
|
||||
soxr==0.3.7
|
||||
spacy==3.7.4
|
||||
spacy-legacy==3.0.12
|
||||
spacy-loggers==1.0.5
|
||||
srsly==2.4.8
|
||||
starlette==0.36.3
|
||||
SudachiDict-core==20240109
|
||||
SudachiPy==0.6.8
|
||||
sympy==1.12
|
||||
tensorboard==2.16.2
|
||||
tensorboard-data-server==0.7.2
|
||||
thinc==8.2.3
|
||||
threadpoolctl==3.4.0
|
||||
tokenizers==0.15.2
|
||||
toolz==0.12.1
|
||||
torch>=2.2.0
|
||||
torchaudio>=2.2.0
|
||||
tqdm==4.66.2
|
||||
trainer==0.0.36
|
||||
transformers==4.39.1
|
||||
TTS==0.22.0
|
||||
typer==0.9.4
|
||||
typing_extensions==4.10.0
|
||||
tzdata==2024.1
|
||||
tzlocal==5.2
|
||||
umap-learn==0.5.5
|
||||
Unidecode==1.3.8
|
||||
unidic-lite==1.0.8
|
||||
urllib3==2.2.1
|
||||
uvicorn==0.29.0
|
||||
wasabi==1.1.2
|
||||
weasel==0.3.4
|
||||
websockets==11.0.3
|
||||
Werkzeug==3.0.1
|
||||
yarl==1.9.4
|
||||
zipp==3.18.1
|
||||
@@ -0,0 +1,171 @@
|
||||
absl-py==2.1.0
|
||||
aiofiles==23.2.1
|
||||
aiohttp==3.9.3
|
||||
aiosignal==1.3.1
|
||||
altair==5.2.0
|
||||
annotated-types==0.6.0
|
||||
anyascii==0.3.2
|
||||
anyio==4.3.0
|
||||
attrs==23.2.0
|
||||
audioread==3.0.1
|
||||
av==11.0.0
|
||||
Babel==2.14.0
|
||||
bangla==0.0.2
|
||||
blinker==1.7.0
|
||||
blis==0.7.11
|
||||
bnnumerizer==0.0.2
|
||||
bnunicodenormalizer==0.1.6
|
||||
catalogue==2.0.10
|
||||
certifi==2024.2.2
|
||||
cffi==1.16.0
|
||||
charset-normalizer==3.3.2
|
||||
click==8.1.7
|
||||
cloudpathlib==0.16.0
|
||||
colorama==0.4.6
|
||||
coloredlogs==15.0.1
|
||||
confection==0.1.4
|
||||
contourpy==1.2.0
|
||||
coqpit==0.0.17
|
||||
ctranslate2==4.1.0
|
||||
cutlet==0.4.0
|
||||
cycler==0.12.1
|
||||
cymem==2.0.8
|
||||
Cython==3.0.9
|
||||
dateparser==1.1.8
|
||||
decorator==5.1.1
|
||||
docopt==0.6.2
|
||||
einops==0.7.0
|
||||
encodec==0.1.1
|
||||
fastapi==0.110.0
|
||||
faster-whisper==1.0.1
|
||||
ffmpy==0.3.2
|
||||
filelock==3.13.3
|
||||
Flask==3.0.2
|
||||
flatbuffers==24.3.25
|
||||
fonttools==4.50.0
|
||||
frozenlist==1.4.1
|
||||
fsspec==2024.3.1
|
||||
fugashi==1.3.1
|
||||
fuzzywuzzy>=0.18.0
|
||||
g2pkk==0.1.2
|
||||
gradio==3.50.2
|
||||
gradio_client==0.6.1
|
||||
grpcio==1.62.1
|
||||
gruut==2.2.3
|
||||
gruut-ipa==0.13.0
|
||||
gruut-lang-de==2.0.0
|
||||
gruut-lang-en==2.0.0
|
||||
gruut-lang-es==2.0.0
|
||||
gruut-lang-fr==2.0.2
|
||||
h11==0.14.0
|
||||
hangul-romanize==0.1.0
|
||||
httpcore==1.0.4
|
||||
httpx==0.27.0
|
||||
huggingface-hub==0.22.1
|
||||
humanfriendly==10.0
|
||||
idna==3.6
|
||||
importlib_metadata==7.1.0
|
||||
importlib_resources==6.4.0
|
||||
inflect==7.0.0
|
||||
itsdangerous==2.1.2
|
||||
jaconv==0.3.4
|
||||
jamo==0.4.1
|
||||
jieba==0.42.1
|
||||
Jinja2==3.1.3
|
||||
joblib==1.3.2
|
||||
jsonlines==1.2.0
|
||||
jsonschema==4.21.1
|
||||
jsonschema-specifications==2023.12.1
|
||||
kiwisolver==1.4.5
|
||||
langcodes==3.3.0
|
||||
lazy_loader==0.3
|
||||
librosa==0.10.1
|
||||
llvmlite==0.42.0
|
||||
Markdown==3.6
|
||||
MarkupSafe==2.1.5
|
||||
matplotlib==3.8.3
|
||||
mojimoji==0.0.13
|
||||
mpmath==1.3.0
|
||||
msgpack==1.0.8
|
||||
multidict==6.0.5
|
||||
murmurhash==1.0.10
|
||||
networkx==2.8.8
|
||||
nltk==3.8.1
|
||||
num2words==0.5.13
|
||||
numba==0.59.1
|
||||
numpy>=1.17.0,<1.29.0
|
||||
nvidia-cublas-cu11>=11.11.3.6
|
||||
nvidia-cudnn-cu11>=9.0.0.312
|
||||
onnxruntime==1.17.1
|
||||
orjson==3.9.15
|
||||
packaging==24.0
|
||||
pandas==1.5.3
|
||||
pillow==10.2.0
|
||||
platformdirs==4.2.0
|
||||
pooch==1.8.1
|
||||
preshed==3.0.9
|
||||
protobuf==5.26.0
|
||||
psutil==5.9.8
|
||||
pycparser==2.21
|
||||
pydantic==2.6.4
|
||||
pydantic_core==2.16.3
|
||||
pydub==0.25.1
|
||||
pynndescent==0.5.11
|
||||
pyparsing==3.1.2
|
||||
pypinyin==0.51.0
|
||||
pyreadline3==3.4.1
|
||||
pysbd==0.3.4
|
||||
python-crfsuite==0.9.10
|
||||
python-dateutil==2.9.0.post0
|
||||
python-Levenshtein>=0.25.0
|
||||
python-multipart==0.0.9
|
||||
pytz==2024.1
|
||||
PyYAML==6.0.1
|
||||
referencing==0.34.0
|
||||
regex==2023.12.25
|
||||
requests==2.31.0
|
||||
rpds-py==0.18.0
|
||||
safetensors==0.4.2
|
||||
scikit-learn==1.4.1.post1
|
||||
scipy==1.12.0
|
||||
semantic-version==2.10.0
|
||||
six==1.16.0
|
||||
smart-open==6.4.0
|
||||
sniffio==1.3.1
|
||||
sounddevice==0.4.6
|
||||
soundfile==0.12.1
|
||||
soxr==0.3.7
|
||||
spacy==3.7.4
|
||||
spacy-legacy==3.0.12
|
||||
spacy-loggers==1.0.5
|
||||
srsly==2.4.8
|
||||
starlette==0.36.3
|
||||
SudachiDict-core==20240109
|
||||
SudachiPy==0.6.8
|
||||
sympy==1.12
|
||||
tensorboard==2.16.2
|
||||
tensorboard-data-server==0.7.2
|
||||
thinc==8.2.3
|
||||
threadpoolctl==3.4.0
|
||||
tokenizers==0.15.2
|
||||
toolz==0.12.1
|
||||
torch>=2.2.0
|
||||
torchaudio>=2.2.0
|
||||
tqdm==4.66.2
|
||||
trainer==0.0.36
|
||||
transformers==4.39.1
|
||||
typer==0.9.4
|
||||
typing_extensions==4.10.0
|
||||
tzdata==2024.1
|
||||
tzlocal==5.2
|
||||
umap-learn==0.5.5
|
||||
Unidecode==1.3.8
|
||||
unidic-lite==1.0.8
|
||||
urllib3==2.2.1
|
||||
uvicorn==0.29.0
|
||||
wasabi==1.1.2
|
||||
weasel==0.3.4
|
||||
websockets==11.0.3
|
||||
Werkzeug==3.0.1
|
||||
yarl==1.9.4
|
||||
zipp==3.18.1
|
||||
@@ -0,0 +1,172 @@
|
||||
absl-py==2.1.0
|
||||
aiofiles==23.2.1
|
||||
aiohttp==3.9.3
|
||||
aiosignal==1.3.1
|
||||
altair==5.2.0
|
||||
annotated-types==0.6.0
|
||||
anyascii==0.3.2
|
||||
anyio==4.3.0
|
||||
attrs==23.2.0
|
||||
audioread==3.0.1
|
||||
av==11.0.0
|
||||
Babel==2.14.0
|
||||
bangla==0.0.2
|
||||
blinker==1.7.0
|
||||
blis==0.7.11
|
||||
bnnumerizer==0.0.2
|
||||
bnunicodenormalizer==0.1.6
|
||||
catalogue==2.0.10
|
||||
certifi==2024.2.2
|
||||
cffi==1.16.0
|
||||
charset-normalizer==3.3.2
|
||||
click==8.1.7
|
||||
cloudpathlib==0.16.0
|
||||
colorama==0.4.6
|
||||
coloredlogs==15.0.1
|
||||
confection==0.1.4
|
||||
contourpy==1.2.0
|
||||
coqpit==0.0.17
|
||||
ctranslate2==4.1.0
|
||||
cutlet==0.4.0
|
||||
cycler==0.12.1
|
||||
cymem==2.0.8
|
||||
Cython==3.0.9
|
||||
dateparser==1.1.8
|
||||
decorator==5.1.1
|
||||
docopt==0.6.2
|
||||
einops==0.7.0
|
||||
encodec==0.1.1
|
||||
fastapi==0.110.0
|
||||
faster-whisper==1.0.1
|
||||
ffmpy==0.3.2
|
||||
filelock==3.13.3
|
||||
Flask==3.0.2
|
||||
flatbuffers==24.3.25
|
||||
fonttools==4.50.0
|
||||
frozenlist==1.4.1
|
||||
fsspec==2024.3.1
|
||||
fugashi==1.3.1
|
||||
fuzzywuzzy>=0.18.0
|
||||
g2pkk==0.1.2
|
||||
gradio==3.50.2
|
||||
gradio_client==0.6.1
|
||||
grpcio==1.62.1
|
||||
gruut==2.2.3
|
||||
gruut-ipa==0.13.0
|
||||
gruut-lang-de==2.0.0
|
||||
gruut-lang-en==2.0.0
|
||||
gruut-lang-es==2.0.0
|
||||
gruut-lang-fr==2.0.2
|
||||
h11==0.14.0
|
||||
hangul-romanize==0.1.0
|
||||
httpcore==1.0.4
|
||||
httpx==0.27.0
|
||||
huggingface-hub==0.22.1
|
||||
humanfriendly==10.0
|
||||
idna==3.6
|
||||
importlib_metadata==7.1.0
|
||||
importlib_resources==6.4.0
|
||||
inflect==7.0.0
|
||||
itsdangerous==2.1.2
|
||||
jaconv==0.3.4
|
||||
jamo==0.4.1
|
||||
jieba==0.42.1
|
||||
Jinja2==3.1.3
|
||||
joblib==1.3.2
|
||||
jsonlines==1.2.0
|
||||
jsonschema==4.21.1
|
||||
jsonschema-specifications==2023.12.1
|
||||
kiwisolver==1.4.5
|
||||
langcodes==3.3.0
|
||||
lazy_loader==0.3
|
||||
librosa==0.10.1
|
||||
llvmlite==0.42.0
|
||||
Markdown==3.6
|
||||
MarkupSafe==2.1.5
|
||||
matplotlib==3.8.3
|
||||
mojimoji==0.0.13
|
||||
mpmath==1.3.0
|
||||
msgpack==1.0.8
|
||||
multidict==6.0.5
|
||||
murmurhash==1.0.10
|
||||
networkx==2.8.8
|
||||
nltk==3.8.1
|
||||
num2words==0.5.13
|
||||
numba==0.59.1
|
||||
numpy==1.26.4
|
||||
nvidia-cublas-cu11>=11.11.3.6
|
||||
nvidia-cudnn-cu11>=9.0.0.312
|
||||
onnxruntime==1.17.1
|
||||
orjson==3.9.15
|
||||
packaging==24.0
|
||||
pandas==1.5.3
|
||||
pillow==10.2.0
|
||||
platformdirs==4.2.0
|
||||
pooch==1.8.1
|
||||
preshed==3.0.9
|
||||
protobuf==5.26.0
|
||||
psutil==5.9.8
|
||||
pycparser==2.21
|
||||
pydantic==2.6.4
|
||||
pydantic_core==2.16.3
|
||||
pydub==0.25.1
|
||||
pynndescent==0.5.11
|
||||
pyparsing==3.1.2
|
||||
pypinyin==0.51.0
|
||||
pyreadline3==3.4.1
|
||||
pysbd==0.3.4
|
||||
python-crfsuite==0.9.10
|
||||
python-dateutil==2.9.0.post0
|
||||
python-Levenshtein>=0.25.0
|
||||
python-multipart==0.0.9
|
||||
pytz==2024.1
|
||||
PyYAML==6.0.1
|
||||
referencing==0.34.0
|
||||
regex==2023.12.25
|
||||
requests==2.31.0
|
||||
rpds-py==0.18.0
|
||||
safetensors==0.4.2
|
||||
scikit-learn==1.4.1.post1
|
||||
scipy==1.12.0
|
||||
semantic-version==2.10.0
|
||||
six==1.16.0
|
||||
smart-open==6.4.0
|
||||
sniffio==1.3.1
|
||||
sounddevice==0.4.6
|
||||
soundfile==0.12.1
|
||||
soxr==0.3.7
|
||||
spacy==3.7.4
|
||||
spacy-legacy==3.0.12
|
||||
spacy-loggers==1.0.5
|
||||
srsly==2.4.8
|
||||
starlette==0.36.3
|
||||
SudachiDict-core==20240109
|
||||
SudachiPy==0.6.8
|
||||
sympy==1.12
|
||||
tensorboard==2.16.2
|
||||
tensorboard-data-server==0.7.2
|
||||
thinc==8.2.3
|
||||
threadpoolctl==3.4.0
|
||||
tokenizers==0.15.2
|
||||
toolz==0.12.1
|
||||
torch>=2.2.0
|
||||
torchaudio>=2.2.0
|
||||
tqdm==4.66.2
|
||||
trainer==0.0.36
|
||||
transformers==4.39.1
|
||||
TTS==0.22.0
|
||||
typer==0.9.4
|
||||
typing_extensions==4.10.0
|
||||
tzdata==2024.1
|
||||
tzlocal==5.2
|
||||
umap-learn==0.5.5
|
||||
Unidecode==1.3.8
|
||||
unidic-lite==1.0.8
|
||||
urllib3==2.2.1
|
||||
uvicorn==0.29.0
|
||||
wasabi==1.1.2
|
||||
weasel==0.3.4
|
||||
websockets==11.0.3
|
||||
Werkzeug==3.0.1
|
||||
yarl==1.9.4
|
||||
zipp==3.18.1
|
||||
@@ -0,0 +1,25 @@
|
||||
numpy>=1.22.0
|
||||
soundfile>=0.12.1
|
||||
uvicorn>=0.24.0.post1
|
||||
transformers>=4.37.1
|
||||
TTS>=0.22.0
|
||||
torch>=2.1.0+cu118
|
||||
torchaudio>=2.1.0+cu118
|
||||
fastapi>=0.104.1
|
||||
Jinja2>=3.1.2
|
||||
requests>=2.31.0
|
||||
tqdm>=4.66.1
|
||||
importlib-metadata>=4.8.1
|
||||
packaging>=23.2
|
||||
pydantic>=1.10.13
|
||||
sounddevice>=0.4.6
|
||||
python-multipart>=0.0.6
|
||||
cutlet>=0.3.0
|
||||
unidic-lite>=1.0.8
|
||||
faster-whisper>=0.10.0
|
||||
pandas>=1.5.0
|
||||
nvidia-cublas-cu11>=11.11.3.6
|
||||
nvidia-cudnn-cu11>=9.0.0.312
|
||||
fuzzywuzzy>=0.18.0
|
||||
python-Levenshtein>=0.25.0
|
||||
spacy>=3.7.2
|
||||
@@ -0,0 +1,833 @@
|
||||
import { doExtrasFetch, getApiUrl, modules } from '../../extensions.js';
|
||||
import { saveTtsProviderSettings } from './index.js';
|
||||
|
||||
export { AllTalkTtsProvider };
|
||||
|
||||
class AllTalkTtsProvider {
|
||||
//########//
|
||||
// Config //
|
||||
//########//
|
||||
|
||||
settings = {};
|
||||
constructor() {
|
||||
// Initialize with default settings if they are not already set
|
||||
this.settings = {
|
||||
provider_endpoint: this.settings.provider_endpoint || 'http://localhost:7851',
|
||||
language: this.settings.language || 'en',
|
||||
voiceMap: this.settings.voiceMap || {},
|
||||
at_generation_method: this.settings.at_generation_method || 'standard_generation',
|
||||
narrator_enabled: this.settings.narrator_enabled || 'false',
|
||||
at_narrator_text_not_inside: this.settings.at_narrator_text_not_inside || 'narrator',
|
||||
narrator_voice_gen: this.settings.narrator_voice_gen || 'female_01.wav',
|
||||
finetuned_model: this.settings.finetuned_model || 'false'
|
||||
};
|
||||
// Separate property for dynamically updated settings from the server
|
||||
this.dynamicSettings = {
|
||||
modelsAvailable: [],
|
||||
currentModel: '',
|
||||
deepspeed_available: false,
|
||||
deepSpeedEnabled: false,
|
||||
lowVramEnabled: false,
|
||||
};
|
||||
}
|
||||
ready = false;
|
||||
voices = [];
|
||||
separator = '. ';
|
||||
audioElement = document.createElement('audio');
|
||||
|
||||
languageLabels = {
|
||||
'Arabic': 'ar',
|
||||
'Brazilian Portuguese': 'pt',
|
||||
'Chinese': 'zh-cn',
|
||||
'Czech': 'cs',
|
||||
'Dutch': 'nl',
|
||||
'English': 'en',
|
||||
'French': 'fr',
|
||||
'German': 'de',
|
||||
'Italian': 'it',
|
||||
'Polish': 'pl',
|
||||
'Russian': 'ru',
|
||||
'Spanish': 'es',
|
||||
'Turkish': 'tr',
|
||||
'Japanese': 'ja',
|
||||
'Korean': 'ko',
|
||||
'Hungarian': 'hu',
|
||||
'Hindi': 'hi',
|
||||
};
|
||||
|
||||
get settingsHtml() {
|
||||
let html = `<div class="at-settings-separator">AllTalk Settings</div>`;
|
||||
|
||||
html += `<div class="at-settings-row">
|
||||
|
||||
<div class="at-settings-option">
|
||||
<label for="at_generation_method">AllTalk TTS Generation Method</label>
|
||||
<select id="at_generation_method">
|
||||
<option value="standard_generation">Standard Audio Generation (AT Narrator - Optional)</option>
|
||||
<option value="streaming_enabled">Streaming Audio Generation (AT Narrator - Disabled)</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>`;
|
||||
|
||||
html += `<div class="at-settings-row">
|
||||
|
||||
<div class="at-settings-option">
|
||||
<label for="at_narrator_enabled">AT Narrator</label>
|
||||
<select id="at_narrator_enabled">
|
||||
<option value="true">Enabled</option>
|
||||
<option value="false">Disabled</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="at-settings-option">
|
||||
<label for="at_narrator_text_not_inside">Text Not Inside * or " is</label>
|
||||
<select id="at_narrator_text_not_inside">
|
||||
<option value="narrator">Narrator</option>
|
||||
<option value="character">Character</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
</div>`;
|
||||
|
||||
html += `<div class="at-settings-row">
|
||||
<div class="at-settings-option">
|
||||
<label for="narrator_voice">Narrator Voice</label>
|
||||
<select id="narrator_voice">`;
|
||||
if (this.voices) {
|
||||
for (let voice of this.voices) {
|
||||
html += `<option value="${voice.voice_id}">${voice.name}</option>`;
|
||||
}
|
||||
}
|
||||
html += `</select>
|
||||
</div>
|
||||
<div class="at-settings-option">
|
||||
<label for="language_options">Language</label>
|
||||
<select id="language_options">`;
|
||||
for (let language in this.languageLabels) {
|
||||
html += `<option value="${this.languageLabels[language]}" ${this.languageLabels[language] === this.settings?.language ? 'selected="selected"' : ''}>${language}</option>`;
|
||||
}
|
||||
html += `</select>
|
||||
</div>
|
||||
</div>`;
|
||||
|
||||
|
||||
html += `<div class="at-model-endpoint-row">
|
||||
<div class="at-model-option">
|
||||
<label for="switch_model">Switch Model</label>
|
||||
<select id="switch_model">
|
||||
<option value="api_tts">API TTS</option>
|
||||
<option value="api_local">API Local</option>
|
||||
<option value="xttsv2_local">XTTSv2 Local</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="at-endpoint-option">
|
||||
<label for="at_server">AllTalk Endpoint:</label>
|
||||
<input id="at_server" type="text" class="text_pole" maxlength="80" value="${this.settings.provider_endpoint}"/>
|
||||
</div>
|
||||
</div>`;
|
||||
|
||||
|
||||
html += `<div class="at-model-endpoint-row">
|
||||
<div class="at-settings-option">
|
||||
<label for="low_vram">Low VRAM</label>
|
||||
<input id="low_vram" type="checkbox"/>
|
||||
</div>
|
||||
<div class="at-settings-option">
|
||||
<label for="deepspeed">DeepSpeed</label>
|
||||
<input id="deepspeed" type="checkbox"/>
|
||||
</div>
|
||||
<div class="at-settings-option status-option">
|
||||
<span>Status: <span id="status_info">Ready</span></span>
|
||||
</div>
|
||||
<div class="at-settings-option empty-option">
|
||||
<!-- This div remains empty for spacing -->
|
||||
</div>
|
||||
</div>`;
|
||||
|
||||
|
||||
html += `<div class="at-website-row">
|
||||
<div class="at-website-option">
|
||||
<span>AllTalk <a target="_blank" href="${this.settings.provider_endpoint}">Config & Docs</a>.</span>
|
||||
</div>
|
||||
|
||||
<div class="at-website-option">
|
||||
<span>AllTalk <a target="_blank" href="https://github.com/erew123/alltalk_tts/">Website</a>.</span>
|
||||
</div>
|
||||
</div>`;
|
||||
|
||||
html += `<div class="at-website-row">
|
||||
<div class="at-website-option">
|
||||
<span><strong>Text-generation-webui</strong> users - Uncheck <strong>Enable TTS</strong> in Text-generation-webui.</span>
|
||||
</div>
|
||||
</div>`;
|
||||
|
||||
return html;
|
||||
}
|
||||
|
||||
|
||||
//#################//
|
||||
// Startup ST & AT //
|
||||
//#################//
|
||||
|
||||
async loadSettings(settings) {
|
||||
updateStatus('Offline');
|
||||
|
||||
if (Object.keys(settings).length === 0) {
|
||||
console.info('Using default AllTalk TTS Provider settings');
|
||||
} else {
|
||||
// Populate settings with provided values, ignoring server-provided settings
|
||||
for (const key in settings) {
|
||||
if (key in this.settings) {
|
||||
this.settings[key] = settings[key];
|
||||
} else {
|
||||
console.debug(`Ignoring non-user-configurable setting: ${key}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update UI elements to reflect the loaded settings
|
||||
$('#at_server').val(this.settings.provider_endpoint);
|
||||
$('#language_options').val(this.settings.language);
|
||||
//$('#voicemap').val(this.settings.voiceMap);
|
||||
$('#at_generation_method').val(this.settings.at_generation_method);
|
||||
$('#at_narrator_enabled').val(this.settings.narrator_enabled);
|
||||
$('#at_narrator_text_not_inside').val(this.settings.at_narrator_text_not_inside);
|
||||
$('#narrator_voice').val(this.settings.narrator_voice_gen);
|
||||
|
||||
console.debug('AllTalkTTS: Settings loaded');
|
||||
try {
|
||||
// Check if TTS provider is ready
|
||||
await this.checkReady();
|
||||
await this.updateSettingsFromServer(); // Fetch dynamic settings from the TTS server
|
||||
await this.fetchTtsVoiceObjects(); // Fetch voices only if service is ready
|
||||
this.updateNarratorVoicesDropdown();
|
||||
this.updateLanguageDropdown();
|
||||
this.setupEventListeners();
|
||||
this.applySettingsToHTML();
|
||||
updateStatus('Ready');
|
||||
} catch (error) {
|
||||
console.error("Error loading settings:", error);
|
||||
updateStatus('Offline');
|
||||
}
|
||||
}
|
||||
|
||||
applySettingsToHTML() {
|
||||
// Apply loaded settings or use defaults
|
||||
const narratorVoiceSelect = document.getElementById('narrator_voice');
|
||||
const atNarratorSelect = document.getElementById('at_narrator_enabled');
|
||||
const textNotInsideSelect = document.getElementById('at_narrator_text_not_inside');
|
||||
const generationMethodSelect = document.getElementById('at_generation_method');
|
||||
this.settings.narrator_voice = this.settings.narrator_voice_gen;
|
||||
// Apply settings to Narrator Voice dropdown
|
||||
if (narratorVoiceSelect && this.settings.narrator_voice) {
|
||||
narratorVoiceSelect.value = this.settings.narrator_voice.replace('.wav', '');
|
||||
}
|
||||
// Apply settings to AT Narrator Enabled dropdown
|
||||
if (atNarratorSelect) {
|
||||
// Sync the state with the checkbox in index.js
|
||||
const ttsPassAsterisksCheckbox = document.getElementById('tts_pass_asterisks'); // Access the checkbox from index.js
|
||||
const ttsNarrateQuotedCheckbox = document.getElementById('tts_narrate_quoted'); // Access the checkbox from index.js
|
||||
const ttsNarrateDialoguesCheckbox = document.getElementById('tts_narrate_dialogues'); // Access the checkbox from index.js
|
||||
// Sync the state with the checkbox in index.js
|
||||
if (this.settings.narrator_enabled) {
|
||||
ttsPassAsterisksCheckbox.checked = false;
|
||||
$('#tts_pass_asterisks').click(); // Simulate a click event
|
||||
$('#tts_pass_asterisks').trigger('change');
|
||||
}
|
||||
if (!this.settings.narrator_enabled) {
|
||||
ttsPassAsterisksCheckbox.checked = true;
|
||||
$('#tts_pass_asterisks').click(); // Simulate a click event
|
||||
$('#tts_pass_asterisks').trigger('change');
|
||||
}
|
||||
// Uncheck and set tts_narrate_quoted to false if narrator is enabled
|
||||
if (this.settings.narrator_enabledd) {
|
||||
ttsNarrateQuotedCheckbox.checked = true;
|
||||
ttsNarrateDialoguesCheckbox.checked = true;
|
||||
// Trigger click events instead of change events
|
||||
$('#tts_narrate_quoted').click();
|
||||
$('#tts_narrate_quoted').trigger('change');
|
||||
$('#tts_narrate_dialogues').click();
|
||||
$('#tts_narrate_dialogues').trigger('change');
|
||||
}
|
||||
atNarratorSelect.value = this.settings.narrator_enabled.toString();
|
||||
this.settings.narrator_enabled = this.settings.narrator_enabled.toString();
|
||||
}
|
||||
// Apply settings to the Language dropdown
|
||||
const languageSelect = document.getElementById('language_options');
|
||||
if (languageSelect && this.settings.language) {
|
||||
languageSelect.value = this.settings.language;
|
||||
}
|
||||
// Apply settings to Text Not Inside dropdown
|
||||
if (textNotInsideSelect && this.settings.text_not_inside) {
|
||||
textNotInsideSelect.value = this.settings.text_not_inside;
|
||||
this.settings.at_narrator_text_not_inside = this.settings.text_not_inside;
|
||||
}
|
||||
// Apply settings to Generation Method dropdown
|
||||
if (generationMethodSelect && this.settings.at_generation_method) {
|
||||
generationMethodSelect.value = this.settings.at_generation_method;
|
||||
}
|
||||
// Additional logic to disable/enable dropdowns based on the selected generation method
|
||||
const isStreamingEnabled = this.settings.at_generation_method === 'streaming_enabled';
|
||||
if (isStreamingEnabled) {
|
||||
// Disable certain dropdowns when streaming is enabled
|
||||
if (atNarratorSelect) atNarratorSelect.disabled = true;
|
||||
if (textNotInsideSelect) textNotInsideSelect.disabled = true;
|
||||
if (narratorVoiceSelect) narratorVoiceSelect.disabled = true;
|
||||
} else {
|
||||
// Enable dropdowns for standard generation
|
||||
if (atNarratorSelect) atNarratorSelect.disabled = false;
|
||||
if (textNotInsideSelect) textNotInsideSelect.disabled = !this.settings.narrator_enabled;
|
||||
if (narratorVoiceSelect) narratorVoiceSelect.disabled = !this.settings.narrator_enabled;
|
||||
}
|
||||
const modelSelect = document.getElementById('switch_model');
|
||||
if (this.settings.finetuned_model === true) {
|
||||
const ftOption = document.createElement('option');
|
||||
ftOption.value = 'XTTSv2 FT';
|
||||
ftOption.textContent = 'XTTSv2 FT';
|
||||
modelSelect.appendChild(ftOption);
|
||||
}
|
||||
}
|
||||
|
||||
//##############################//
|
||||
// Check AT Server is Available //
|
||||
//##############################//
|
||||
|
||||
async checkReady() {
|
||||
try {
|
||||
const response = await fetch(`${this.settings.provider_endpoint}/api/ready`);
|
||||
// Check if the HTTP request was successful
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP Error Response: ${response.status} ${response.statusText}`);
|
||||
}
|
||||
const statusText = await response.text();
|
||||
// Check if the response is 'Ready'
|
||||
if (statusText === 'Ready') {
|
||||
this.ready = true; // Set the ready flag to true
|
||||
console.log('TTS service is ready.');
|
||||
} else {
|
||||
this.ready = false;
|
||||
console.log('TTS service is not ready.');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error checking TTS service readiness:', error);
|
||||
this.ready = false; // Ensure ready flag is set to false in case of error
|
||||
}
|
||||
}
|
||||
|
||||
//######################//
|
||||
// Get Available Voices //
|
||||
//######################//
|
||||
|
||||
async fetchTtsVoiceObjects() {
|
||||
const response = await fetch(`${this.settings.provider_endpoint}/api/voices`);
|
||||
if (!response.ok) {
|
||||
const errorText = await response.text();
|
||||
throw new Error(`HTTP ${response.status}: ${errorText}`);
|
||||
}
|
||||
const data = await response.json();
|
||||
const voices = data.voices.map(filename => {
|
||||
const voiceName = filename.replace('.wav', '');
|
||||
return {
|
||||
name: voiceName,
|
||||
voice_id: voiceName,
|
||||
preview_url: null, // Preview URL will be dynamically generated
|
||||
lang: 'en' // Default language
|
||||
};
|
||||
});
|
||||
this.voices = voices; // Assign to the class property
|
||||
return voices; // Also return this list
|
||||
}
|
||||
|
||||
//##########################################//
|
||||
// Get Current AT Server Config & Update ST //
|
||||
//##########################################//
|
||||
|
||||
async updateSettingsFromServer() {
|
||||
try {
|
||||
// Fetch current settings
|
||||
const response = await fetch(`${this.settings.provider_endpoint}/api/currentsettings`);
|
||||
if (!response.ok) {
|
||||
throw new Error(`Failed to fetch current settings: ${response.statusText}`);
|
||||
}
|
||||
const currentSettings = await response.json();
|
||||
// Update internal settings
|
||||
this.settings.modelsAvailable = currentSettings.models_available;
|
||||
this.settings.currentModel = currentSettings.current_model_loaded;
|
||||
this.settings.deepspeed_available = currentSettings.deepspeed_available;
|
||||
this.settings.deepSpeedEnabled = currentSettings.deepspeed_status;
|
||||
this.settings.lowVramEnabled = currentSettings.low_vram_status;
|
||||
this.settings.finetuned_model = currentSettings.finetuned_model
|
||||
// Update HTML elements
|
||||
this.updateModelDropdown();
|
||||
this.updateCheckboxes();
|
||||
} catch (error) {
|
||||
console.error(`Error updating settings from server: ${error}`);
|
||||
}
|
||||
}
|
||||
|
||||
//###################################################//
|
||||
// Get Current AT Server Config & Update ST (Models) //
|
||||
//###################################################//
|
||||
|
||||
updateModelDropdown() {
|
||||
const modelSelect = document.getElementById('switch_model');
|
||||
if (modelSelect) {
|
||||
modelSelect.innerHTML = ''; // Clear existing options
|
||||
this.settings.modelsAvailable.forEach(model => {
|
||||
const option = document.createElement('option');
|
||||
option.value = model.model_name;
|
||||
option.textContent = model.model_name; // Use model_name instead of name
|
||||
option.selected = model.model_name === this.settings.currentModel;
|
||||
modelSelect.appendChild(option);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
//#######################################################//
|
||||
// Get Current AT Server Config & Update ST (DS and LVR) //
|
||||
//#######################################################//
|
||||
|
||||
updateCheckboxes() {
|
||||
const deepspeedCheckbox = document.getElementById('deepspeed');
|
||||
const lowVramCheckbox = document.getElementById('low_vram');
|
||||
if (lowVramCheckbox) lowVramCheckbox.checked = this.settings.lowVramEnabled;
|
||||
if (deepspeedCheckbox) {
|
||||
deepspeedCheckbox.checked = this.settings.deepSpeedEnabled;
|
||||
deepspeedCheckbox.disabled = !this.settings.deepspeed_available; // Disable checkbox if deepspeed is not available
|
||||
}
|
||||
}
|
||||
|
||||
//###############################################################//
|
||||
// Get Current AT Server Config & Update ST (AT Narrator Voices) //
|
||||
//###############################################################//
|
||||
|
||||
updateNarratorVoicesDropdown() {
|
||||
const narratorVoiceSelect = document.getElementById('narrator_voice');
|
||||
if (narratorVoiceSelect && this.voices) {
|
||||
// Clear existing options
|
||||
narratorVoiceSelect.innerHTML = '';
|
||||
// Add new options
|
||||
for (let voice of this.voices) {
|
||||
const option = document.createElement('option');
|
||||
option.value = voice.voice_id;
|
||||
option.textContent = voice.name;
|
||||
narratorVoiceSelect.appendChild(option);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//######################################################//
|
||||
// Get Current AT Server Config & Update ST (Languages) //
|
||||
//######################################################//
|
||||
|
||||
updateLanguageDropdown() {
|
||||
const languageSelect = document.getElementById('language_options');
|
||||
if (languageSelect) {
|
||||
// Ensure default language is set
|
||||
this.settings.language = this.settings.language;
|
||||
|
||||
languageSelect.innerHTML = '';
|
||||
for (let language in this.languageLabels) {
|
||||
const option = document.createElement('option');
|
||||
option.value = this.languageLabels[language];
|
||||
option.textContent = language;
|
||||
if (this.languageLabels[language] === this.settings.language) {
|
||||
option.selected = true;
|
||||
}
|
||||
languageSelect.appendChild(option);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//########################################//
|
||||
// Start AT TTS extenstion page listeners //
|
||||
//########################################//
|
||||
|
||||
setupEventListeners() {
|
||||
|
||||
let debounceTimeout;
|
||||
const debounceDelay = 500; // Milliseconds
|
||||
|
||||
// Define the event handler function
|
||||
const onModelSelectChange = async (event) => {
|
||||
console.log("Model select change event triggered"); // Debugging statement
|
||||
const selectedModel = event.target.value;
|
||||
console.log(`Selected model: ${selectedModel}`); // Debugging statement
|
||||
// Set status to Processing
|
||||
updateStatus('Processing');
|
||||
try {
|
||||
const response = await fetch(`${this.settings.provider_endpoint}/api/reload?tts_method=${encodeURIComponent(selectedModel)}`, {
|
||||
method: 'POST'
|
||||
});
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP Error: ${response.status}`);
|
||||
}
|
||||
const data = await response.json();
|
||||
console.log("POST response data:", data); // Debugging statement
|
||||
// Set status to Ready if successful
|
||||
updateStatus('Ready');
|
||||
} catch (error) {
|
||||
console.error("POST request error:", error); // Debugging statement
|
||||
// Set status to Error in case of failure
|
||||
updateStatus('Error');
|
||||
}
|
||||
|
||||
// Handle response or error
|
||||
};
|
||||
|
||||
const debouncedModelSelectChange = (event) => {
|
||||
clearTimeout(debounceTimeout);
|
||||
debounceTimeout = setTimeout(() => {
|
||||
onModelSelectChange(event);
|
||||
}, debounceDelay);
|
||||
};
|
||||
|
||||
// Switch Model Listener
|
||||
const modelSelect = document.getElementById('switch_model');
|
||||
if (modelSelect) {
|
||||
// Remove the event listener if it was previously added
|
||||
modelSelect.removeEventListener('change', debouncedModelSelectChange);
|
||||
// Add the debounced event listener
|
||||
modelSelect.addEventListener('change', debouncedModelSelectChange);
|
||||
}
|
||||
|
||||
// DeepSpeed Listener
|
||||
const deepspeedCheckbox = document.getElementById('deepspeed');
|
||||
if (deepspeedCheckbox) {
|
||||
deepspeedCheckbox.addEventListener('change', async (event) => {
|
||||
const deepSpeedValue = event.target.checked ? 'True' : 'False';
|
||||
// Set status to Processing
|
||||
updateStatus('Processing');
|
||||
try {
|
||||
const response = await fetch(`${this.settings.provider_endpoint}/api/deepspeed?new_deepspeed_value=${deepSpeedValue}`, {
|
||||
method: 'POST'
|
||||
});
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP Error: ${response.status}`);
|
||||
}
|
||||
const data = await response.json();
|
||||
console.log("POST response data:", data); // Debugging statement
|
||||
// Set status to Ready if successful
|
||||
updateStatus('Ready');
|
||||
} catch (error) {
|
||||
console.error("POST request error:", error); // Debugging statement
|
||||
// Set status to Error in case of failure
|
||||
updateStatus('Error');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Low VRAM Listener
|
||||
const lowVramCheckbox = document.getElementById('low_vram');
|
||||
if (lowVramCheckbox) {
|
||||
lowVramCheckbox.addEventListener('change', async (event) => {
|
||||
const lowVramValue = event.target.checked ? 'True' : 'False';
|
||||
// Set status to Processing
|
||||
updateStatus('Processing');
|
||||
try {
|
||||
const response = await fetch(`${this.settings.provider_endpoint}/api/lowvramsetting?new_low_vram_value=${lowVramValue}`, {
|
||||
method: 'POST'
|
||||
});
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP Error: ${response.status}`);
|
||||
}
|
||||
const data = await response.json();
|
||||
console.log("POST response data:", data); // Debugging statement
|
||||
// Set status to Ready if successful
|
||||
updateStatus('Ready');
|
||||
} catch (error) {
|
||||
console.error("POST request error:", error); // Debugging statement
|
||||
// Set status to Error in case of failure
|
||||
updateStatus('Error');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Narrator Voice Dropdown Listener
|
||||
const narratorVoiceSelect = document.getElementById('narrator_voice');
|
||||
if (narratorVoiceSelect) {
|
||||
narratorVoiceSelect.addEventListener('change', (event) => {
|
||||
this.settings.narrator_voice_gen = `${event.target.value}.wav`;
|
||||
this.onSettingsChange(); // Save the settings after change
|
||||
});
|
||||
}
|
||||
|
||||
const textNotInsideSelect = document.getElementById('at_narrator_text_not_inside');
|
||||
if (textNotInsideSelect) {
|
||||
textNotInsideSelect.addEventListener('change', (event) => {
|
||||
this.settings.text_not_inside = event.target.value;
|
||||
this.onSettingsChange(); // Save the settings after change
|
||||
});
|
||||
}
|
||||
|
||||
// AT Narrator Dropdown Listener
|
||||
const atNarratorSelect = document.getElementById('at_narrator_enabled');
|
||||
const ttsPassAsterisksCheckbox = document.getElementById('tts_pass_asterisks'); // Access the checkbox from index.js
|
||||
const ttsNarrateQuotedCheckbox = document.getElementById('tts_narrate_quoted'); // Access the checkbox from index.js
|
||||
const ttsNarrateDialoguesCheckbox = document.getElementById('tts_narrate_dialogues'); // Access the checkbox from index.js
|
||||
|
||||
if (atNarratorSelect && textNotInsideSelect && narratorVoiceSelect) {
|
||||
atNarratorSelect.addEventListener('change', (event) => {
|
||||
const isNarratorEnabled = event.target.value === 'true';
|
||||
this.settings.narrator_enabled = isNarratorEnabled; // Update the setting here
|
||||
textNotInsideSelect.disabled = !isNarratorEnabled;
|
||||
narratorVoiceSelect.disabled = !isNarratorEnabled;
|
||||
|
||||
// Sync the state with the checkbox in index.js
|
||||
if (isNarratorEnabled) {
|
||||
ttsPassAsterisksCheckbox.checked = false;
|
||||
$('#tts_pass_asterisks').click(); // Simulate a click event
|
||||
$('#tts_pass_asterisks').trigger('change');
|
||||
}
|
||||
if (!isNarratorEnabled) {
|
||||
ttsPassAsterisksCheckbox.checked = true;
|
||||
$('#tts_pass_asterisks').click(); // Simulate a click event
|
||||
$('#tts_pass_asterisks').trigger('change');
|
||||
}
|
||||
// Uncheck and set tts_narrate_quoted to false if narrator is enabled
|
||||
if (isNarratorEnabled) {
|
||||
ttsNarrateQuotedCheckbox.checked = true;
|
||||
ttsNarrateDialoguesCheckbox.checked = true;
|
||||
// Trigger click events instead of change events
|
||||
$('#tts_narrate_quoted').click();
|
||||
$('#tts_narrate_quoted').trigger('change');
|
||||
$('#tts_narrate_dialogues').click();
|
||||
$('#tts_narrate_dialogues').trigger('change');
|
||||
}
|
||||
this.onSettingsChange(); // Save the settings after change
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// Event Listener for AT Generation Method Dropdown
|
||||
const atGenerationMethodSelect = document.getElementById('at_generation_method');
|
||||
const atNarratorEnabledSelect = document.getElementById('at_narrator_enabled');
|
||||
if (atGenerationMethodSelect) {
|
||||
atGenerationMethodSelect.addEventListener('change', (event) => {
|
||||
const selectedMethod = event.target.value;
|
||||
|
||||
if (selectedMethod === 'streaming_enabled') {
|
||||
// Disable and unselect AT Narrator
|
||||
atNarratorEnabledSelect.disabled = true;
|
||||
atNarratorEnabledSelect.value = 'false';
|
||||
textNotInsideSelect.disabled = true;
|
||||
narratorVoiceSelect.disabled = true;
|
||||
} else if (selectedMethod === 'standard_generation') {
|
||||
// Enable AT Narrator
|
||||
atNarratorEnabledSelect.disabled = false;
|
||||
}
|
||||
this.settings.at_generation_method = selectedMethod; // Update the setting here
|
||||
this.onSettingsChange(); // Save the settings after change
|
||||
});
|
||||
}
|
||||
|
||||
// Listener for Language Dropdown
|
||||
const languageSelect = document.getElementById('language_options');
|
||||
if (languageSelect) {
|
||||
languageSelect.addEventListener('change', (event) => {
|
||||
this.settings.language = event.target.value;
|
||||
this.onSettingsChange(); // Save the settings after change
|
||||
});
|
||||
}
|
||||
|
||||
// Listener for AllTalk Endpoint Input
|
||||
const atServerInput = document.getElementById('at_server');
|
||||
if (atServerInput) {
|
||||
atServerInput.addEventListener('input', (event) => {
|
||||
this.settings.provider_endpoint = event.target.value;
|
||||
this.onSettingsChange(); // Save the settings after change
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//#############################//
|
||||
// Store ST interface settings //
|
||||
//#############################//
|
||||
|
||||
onSettingsChange() {
|
||||
// Update settings based on the UI elements
|
||||
//this.settings.provider_endpoint = $('#at_server').val();
|
||||
this.settings.language = $('#language_options').val();
|
||||
//this.settings.voiceMap = $('#voicemap').val();
|
||||
this.settings.at_generation_method = $('#at_generation_method').val();
|
||||
this.settings.narrator_enabled = $('#at_narrator_enabled').val();
|
||||
this.settings.at_narrator_text_not_inside = $('#at_narrator_text_not_inside').val();
|
||||
this.settings.narrator_voice_gen = $('#narrator_voice').val();
|
||||
// Save the updated settings
|
||||
saveTtsProviderSettings();
|
||||
}
|
||||
|
||||
//#########################//
|
||||
// ST Handle Reload button //
|
||||
//#########################//
|
||||
|
||||
async onRefreshClick() {
|
||||
await this.checkReady(); // Check if the TTS provider is ready
|
||||
await this.loadSettings(this.settings); // Reload the settings
|
||||
// Additional actions as needed
|
||||
}
|
||||
|
||||
//##################//
|
||||
// Preview AT Voice //
|
||||
//##################//
|
||||
|
||||
async previewTtsVoice(voiceName) {
|
||||
try {
|
||||
// Prepare data for POST request
|
||||
const postData = new URLSearchParams();
|
||||
postData.append("voice", `${voiceName}.wav`);
|
||||
// Making the POST request
|
||||
const response = await fetch(`${this.settings.provider_endpoint}/api/previewvoice/`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded'
|
||||
},
|
||||
body: postData,
|
||||
});
|
||||
if (!response.ok) {
|
||||
const errorText = await response.text();
|
||||
console.error(`[previewTtsVoice] Error Response Text:`, errorText);
|
||||
throw new Error(`HTTP ${response.status}: ${errorText}`);
|
||||
}
|
||||
// Assuming the server returns a URL to the .wav file
|
||||
const data = await response.json();
|
||||
if (data.output_file_url) {
|
||||
// Use an audio element to play the .wav file
|
||||
const audioElement = new Audio(data.output_file_url);
|
||||
audioElement.play().catch(e => console.error("Error playing audio:", e));
|
||||
} else {
|
||||
console.warn("[previewTtsVoice] No output file URL received in the response");
|
||||
throw new Error("No output file URL received in the response");
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error("[previewTtsVoice] Exception caught during preview generation:", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
//#####################//
|
||||
// Populate ST voices //
|
||||
//#####################//
|
||||
|
||||
async getVoice(voiceName, generatePreview = false) {
|
||||
// Ensure this.voices is populated
|
||||
if (this.voices.length === 0) {
|
||||
// Fetch voice objects logic
|
||||
}
|
||||
// Find the object where the name matches voiceName
|
||||
const match = this.voices.find(voice => voice.name === voiceName);
|
||||
if (!match) {
|
||||
// Error handling
|
||||
}
|
||||
// Generate preview URL only if requested
|
||||
if (!match.preview_url && generatePreview) {
|
||||
// Generate preview logic
|
||||
}
|
||||
return match; // Return the found voice object
|
||||
}
|
||||
|
||||
//##########################################//
|
||||
// Generate TTS Streaming or call Standard //
|
||||
//##########################################//
|
||||
|
||||
async generateTts(inputText, voiceId) {
|
||||
try {
|
||||
if (this.settings.at_generation_method === 'streaming_enabled') {
|
||||
// Construct the streaming URL
|
||||
const streamingUrl = `${this.settings.provider_endpoint}/api/tts-generate-streaming?text=${encodeURIComponent(inputText)}&voice=${encodeURIComponent(voiceId)}.wav&language=${encodeURIComponent(this.settings.language)}&output_file=stream_output.wav`;
|
||||
console.log("Streaming URL:", streamingUrl);
|
||||
|
||||
// Return the streaming URL directly
|
||||
return streamingUrl;
|
||||
} else {
|
||||
// For standard method
|
||||
const outputUrl = await this.fetchTtsGeneration(inputText, voiceId);
|
||||
const audioResponse = await fetch(outputUrl);
|
||||
if (!audioResponse.ok) {
|
||||
throw new Error(`HTTP ${audioResponse.status}: Failed to fetch audio data`);
|
||||
}
|
||||
return audioResponse; // Return the fetch response directly
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error in generateTts:", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//####################//
|
||||
// Generate Standard //
|
||||
//####################//
|
||||
|
||||
async fetchTtsGeneration(inputText, voiceId) {
|
||||
// Prepare the request payload
|
||||
const requestBody = new URLSearchParams({
|
||||
'text_input': inputText,
|
||||
'text_filtering': "standard",
|
||||
'character_voice_gen': voiceId + ".wav",
|
||||
'narrator_enabled': this.settings.narrator_enabled,
|
||||
'narrator_voice_gen': this.settings.narrator_voice_gen + ".wav",
|
||||
'text_not_inside': this.settings.at_narrator_text_not_inside,
|
||||
'language': this.settings.language,
|
||||
'output_file_name': "st_output",
|
||||
'output_file_timestamp': "true",
|
||||
'autoplay': "false",
|
||||
'autoplay_volume': "0.8"
|
||||
}).toString();
|
||||
|
||||
try {
|
||||
const response = await doExtrasFetch(
|
||||
`${this.settings.provider_endpoint}/api/tts-generate`,
|
||||
{
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
'Cache-Control': 'no-cache',
|
||||
},
|
||||
body: requestBody
|
||||
}
|
||||
);
|
||||
|
||||
if (!response.ok) {
|
||||
const errorText = await response.text();
|
||||
console.error(`[fetchTtsGeneration] Error Response Text:`, errorText);
|
||||
// toastr.error(response.statusText, 'TTS Generation Failed');
|
||||
throw new Error(`HTTP ${response.status}: ${errorText}`);
|
||||
}
|
||||
const data = await response.json();
|
||||
const outputUrl = data.output_file_url;
|
||||
return outputUrl; // Return only the output_file_url
|
||||
} catch (error) {
|
||||
console.error("[fetchTtsGeneration] Exception caught:", error);
|
||||
throw error; // Rethrow the error for further handling
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//#########################//
|
||||
// Update Status Messages //
|
||||
//#########################//
|
||||
|
||||
function updateStatus(message) {
|
||||
const statusElement = document.getElementById('status_info');
|
||||
if (statusElement) {
|
||||
statusElement.textContent = message;
|
||||
switch (message) {
|
||||
case 'Offline':
|
||||
statusElement.style.color = 'red';
|
||||
break;
|
||||
case 'Ready':
|
||||
statusElement.style.color = 'lightgreen';
|
||||
break;
|
||||
case 'Processing':
|
||||
statusElement.style.color = 'blue';
|
||||
break;
|
||||
case 'Error':
|
||||
statusElement.style.color = 'red';
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
#tts_media_control {
|
||||
/* order: 100; */
|
||||
/* width: 40px;
|
||||
height: 40px;
|
||||
margin: 0;
|
||||
padding: 1px; */
|
||||
outline: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
/* transition: 0.3s;
|
||||
opacity: 0.7; */
|
||||
display: flex;
|
||||
align-items: center;
|
||||
/* justify-content: center; */
|
||||
|
||||
}
|
||||
|
||||
#ttsExtensionMenuItem {
|
||||
transition: 0.3s;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
#ttsExtensionMenuItem:hover {
|
||||
opacity: 1;
|
||||
filter: brightness(1.2);
|
||||
}
|
||||
|
||||
#tts_media_control:hover {
|
||||
opacity: 1;
|
||||
filter: brightness(1.2);
|
||||
}
|
||||
|
||||
.voice_preview {
|
||||
margin: 0.25rem 0.5rem;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.voice_preview .voice_name {
|
||||
text-align: left;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.voice_preview .voice_lang {
|
||||
width: 4rem;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.voice_preview .fa-play {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.tts-button {
|
||||
margin: 0;
|
||||
outline: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
transition: 0.3s;
|
||||
opacity: 0.7;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
}
|
||||
|
||||
.tts-button:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.tts_block {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
column-gap: 5px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.tts_custom_voices {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
gap: 5px;
|
||||
}
|
||||
|
||||
.novel_tts_hints {
|
||||
font-size: calc(0.9 * var(--mainFontSize));
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 5px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.at-settings-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.at-settings-option {
|
||||
flex: 1;
|
||||
margin: 0 10px;
|
||||
}
|
||||
|
||||
.at-endpoint-option {
|
||||
flex: 1;
|
||||
margin: 0 10px;
|
||||
margin-right: 25px;
|
||||
width: 38%;
|
||||
}
|
||||
|
||||
.at-website-row {
|
||||
display: flex;
|
||||
justify-content: start;
|
||||
align-items: center;
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.at-website-option {
|
||||
flex: 1;
|
||||
margin-right: 10px;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.at-settings-separator {
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
padding: 18x;
|
||||
font-weight: bold;
|
||||
border-top: 1px solid #e1e1e1; /* Grey line */
|
||||
border-bottom: 1px solid #e1e1e1; /* Grey line */
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.at-status-message {
|
||||
flex: 1;
|
||||
margin: 0 10px;
|
||||
}
|
||||
|
||||
.at-model-endpoint-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.at-model-option, .endpoint-option {
|
||||
flex: 1;
|
||||
margin: 0 10px;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.at-endpoint-option {
|
||||
width: 38%;
|
||||
}
|
||||
|
||||
#at-status_info {
|
||||
color: lightgreen;
|
||||
}
|
||||
@@ -0,0 +1,269 @@
|
||||
import json
|
||||
import argparse
|
||||
from pathlib import Path
|
||||
import os
|
||||
import glob
|
||||
import platform
|
||||
import site
|
||||
import subprocess
|
||||
import sys
|
||||
# version 0.8
|
||||
|
||||
def find_files_in_path_with_wildcard(pattern):
|
||||
# Get the site-packages directory of the current Python environment
|
||||
site_packages_path = site.getsitepackages()
|
||||
found_paths = []
|
||||
# Adjust the sub-directory based on the operating system
|
||||
sub_directory = "nvidia/cublas"
|
||||
if platform.system() == "Linux":
|
||||
sub_directory = os.path.join(sub_directory, "lib")
|
||||
else:
|
||||
sub_directory = os.path.join(sub_directory, "bin")
|
||||
|
||||
# Iterate over each site-packages directory (there can be more than one)
|
||||
for directory in site_packages_path:
|
||||
# Construct the search directory path
|
||||
search_directory = os.path.join(directory, sub_directory)
|
||||
# Use glob to find all files matching the pattern in this directory
|
||||
for file_path in glob.glob(os.path.join(search_directory, pattern)):
|
||||
if os.path.isfile(file_path): # Ensure it's a file
|
||||
found_paths.append(file_path)
|
||||
return found_paths
|
||||
|
||||
def detect_cublas():
|
||||
# Use different file patterns based on the operating system
|
||||
file_name_pattern = 'cublas64_11.*' if platform.system() == "Windows" else 'libcublas.so.11*'
|
||||
found_paths = find_files_in_path_with_wildcard(file_name_pattern)
|
||||
if found_paths:
|
||||
print("[AllTalk TTSDiff] \033[94mCublas:\033[0m \033[92mDetected\033[0m", found_paths)
|
||||
else:
|
||||
print("[AllTalk TTSDiff] \033[94mCublas:\033[0m \033[91mERROR Not Detected\033[0m")
|
||||
print("[AllTalk TTSDiff] \033[94mPlease install Cublas from the Nvidia CUDA Toolkit \033[0mhttps://developer.nvidia.com/cuda-downloads")
|
||||
exit(1)
|
||||
|
||||
|
||||
parser = argparse.ArgumentParser(description="Compare TTS output with the original text using detailed comparison.")
|
||||
parser.add_argument("--threshold", type=int, default=98, help="Similarity threshold for considering a match (default: 98)")
|
||||
parser.add_argument("--ttslistpath", help="Path to the ttsList.json file")
|
||||
parser.add_argument("--wavfilespath", help="Path to the wav outputs folder")
|
||||
args = parser.parse_args()
|
||||
|
||||
if not args.ttslistpath:
|
||||
parser.error("[AllTalk TTSDiff] Please specify the path to the ttslist.json file using the --ttslistpath argument.")
|
||||
if not args.wavfilespath:
|
||||
parser.error("[AllTalk TTSDiff] Please specify the path to the wavs output folder file using the --wavfilespath argument.")
|
||||
|
||||
json_file_path = Path(args.ttslistpath).resolve()
|
||||
wav_file_path = Path(args.wavfilespath).resolve()
|
||||
accuracy_threshold = args.threshold
|
||||
|
||||
def disclaimer_text():
|
||||
print(f"\nDESCRIPTION: ")
|
||||
print(f" This script is designed to assist in identifying bad TTS generation ID's from the TTS Generator.\n")
|
||||
print(f" This will download the Whisper Large-v2 model (if not already downloaded), and use it to compare your text to")
|
||||
print(f" to the generated TTS. If it finds an issue, it will flag the ID number that has the issue. This does NOT 100%")
|
||||
print(f" ensure that all TTS generated is perfect, sounds good etc, but it should flag up glaring issues and help with")
|
||||
print(f" the process of identifying bad TTS generations.")
|
||||
print(f"\nNOTES ON USE: ")
|
||||
print(f" - Ensure AllTalk is running in its own command prompt/terminal.")
|
||||
print(f" - This script should be running in its own command prompt/terminal window in the same Python Environment that")
|
||||
print(f" AllTalk is running in.")
|
||||
print(f" - After generating your text in the TTS Generator, you need to `Export List to JSON` and save the file in the")
|
||||
print(f" same folder/directory this script is running from.")
|
||||
print(f" - You can use `--threshold` with a numerical value from 1 to 100 to set accuracy detection. For example it may")
|
||||
print(f" detect/transcribe `their` as `there`, which of course, both words sound the same. If you want 100% accuracy")
|
||||
print(f" you will set 100 as the threshold. You will more than likely want a number in the high 90's. Default is set")
|
||||
print(f" at 98, which gives a little flexibility.")
|
||||
print(f" - The JSON file must be named \033[93mttsList.json\033[0m")
|
||||
print(f" - When you have your ID list, go back into the TTS Generator, correct any lines and regenerate them. If you")
|
||||
print(f" want to re-test everthing again after re-generating, you will need to export your list again and re-run this")
|
||||
print(f" script again, against your newly exported JSON list.")
|
||||
print(f" - This requires access to \033[93mcublas64_11\033[0m, the same as Finetuning.")
|
||||
print(f" https://github.com/erew123/alltalk_tts/tree/main?#-important-requirements-cuda-118\n")
|
||||
return
|
||||
|
||||
try:
|
||||
from faster_whisper import WhisperModel
|
||||
import re
|
||||
import string
|
||||
import spacy
|
||||
import torch
|
||||
from fuzzywuzzy import fuzz
|
||||
except ImportError as e:
|
||||
print(f"[AllTalk TTSDiff] ERROR STARTING SCRIPT:")
|
||||
print("[AllTalk TTSDiff] An error occurred importing one or more required libraries.")
|
||||
print("[AllTalk TTSDiff] Please ensure you have \033[94mactivated your Python environment \033[0mand \033[94minstalled all requirements.\033[0m")
|
||||
print("[AllTalk TTSDiff] \033[94mMissing library:\033[93m", str(e), "\033[0m")
|
||||
exit(1)
|
||||
|
||||
# Attempt to load the spaCy model
|
||||
try:
|
||||
# Load a medium-sized spaCy model, adjust to "en_core_web_md" or "en_core_web_lg" as needed
|
||||
nlp = spacy.load("en_core_web_md")
|
||||
except Exception as e:
|
||||
print(f"[AllTalk TTSDiff] ERROR STARTING SCRIPT:")
|
||||
print("[AllTalk TTSDiff] Failed to load the spaCy language model.")
|
||||
|
||||
# Attempt to download the spaCy model automatically
|
||||
try:
|
||||
print("[AllTalk TTSDiff] Attempting to automatically download the spaCy language model...")
|
||||
subprocess.run([sys.executable, "-m", "spacy", "download", "en_core_web_md"], check=True)
|
||||
|
||||
# Try to load the model again after downloading
|
||||
nlp = spacy.load("en_core_web_md")
|
||||
print("[AllTalk TTSDiff] Model downloaded and loaded successfully.")
|
||||
except Exception as download_exception:
|
||||
print("[AllTalk TTSDiff] Automatic download failed.")
|
||||
print("[AllTalk TTSDiff] Please manually install the spaCy language model by running:")
|
||||
print("[AllTalk TTSDiff] \033[93mpython -m spacy download en_core_web_md\033[0m")
|
||||
exit(1)
|
||||
|
||||
def texts_are_similar(text1, text2, threshold=0.8):
|
||||
# Preliminary check for short texts
|
||||
if len(text1) < 10 or len(text2) < 10:
|
||||
ratio = fuzz.ratio(text1, text2) / 100.0 # Use FuzzyWuzzy for short texts
|
||||
return ratio > threshold
|
||||
|
||||
# Process the texts through the NLP model for longer texts
|
||||
doc1 = nlp(text1)
|
||||
doc2 = nlp(text2)
|
||||
|
||||
# Compute semantic similarity
|
||||
similarity = doc1.similarity(doc2)
|
||||
|
||||
return similarity >= threshold
|
||||
|
||||
def normalize_text(text):
|
||||
# Normalize or remove CRLF and other non-standard whitespaces
|
||||
text = text.replace("\r\n", " ").replace("\n", " ").replace("\r", " ")
|
||||
|
||||
# Convert to lowercase
|
||||
text = text.lower()
|
||||
|
||||
# Standardize and then remove quotation marks
|
||||
text = text.replace("“", '"').replace("”", '"').replace("‘", "'").replace("’", "'")
|
||||
text = text.translate(str.maketrans('', '', '"\''))
|
||||
|
||||
# Remove all other punctuation except hyphens to preserve compound words
|
||||
text = text.translate(str.maketrans('', '', string.punctuation.replace("-", "")))
|
||||
|
||||
# Collapse any sequence of whitespace (including spaces) into a single space
|
||||
text = re.sub(r'\s+', ' ', text)
|
||||
|
||||
return text.strip()
|
||||
|
||||
spoken_punctuation_mapping = {
|
||||
"dot": ".",
|
||||
"comma": ",",
|
||||
# Add more mappings as needed
|
||||
}
|
||||
|
||||
def contains_spoken_punctuation(transcribed_text):
|
||||
for spoken, punctuation in spoken_punctuation_mapping.items():
|
||||
if spoken in transcribed_text:
|
||||
return True
|
||||
return False
|
||||
|
||||
def detailed_comparison(original_text, transcribed_text, threshold=98):
|
||||
original_clean = normalize_text(original_text)
|
||||
transcribed_clean = normalize_text(transcribed_text)
|
||||
ratio = fuzz.ratio(original_clean, transcribed_clean)
|
||||
return ratio > threshold
|
||||
|
||||
def access_local_file(url):
|
||||
# Extract the file name from the URL
|
||||
file_name = url.split('/')[-1]
|
||||
# Construct the full path to the file on disk
|
||||
file_path = wav_file_path / file_name
|
||||
# Check if the file exists
|
||||
if not file_path.exists():
|
||||
print(f"[AllTalk TTSDiff] File does not exist: {file_path}")
|
||||
return None
|
||||
return file_path
|
||||
|
||||
def transcribe_and_compare(file_url, original_text, model, item_id, flagged_ids):
|
||||
audio_file_path = access_local_file(file_url)
|
||||
if audio_file_path is None:
|
||||
print(f"[AllTalk TTSDiff] Could not access local file for URL: {file_url}")
|
||||
return # Skip this file if it can't be accessed
|
||||
|
||||
try:
|
||||
segments, info = model.transcribe(str(audio_file_path), beam_size=5)
|
||||
transcribed_text = " ".join([segment.text for segment in segments])
|
||||
except Exception as e:
|
||||
print(f"[AllTalk TTSDiff] Error transcribing file {audio_file_path}: {e}")
|
||||
return # Skip this file if transcription fails
|
||||
|
||||
segments, info = model.transcribe(str(audio_file_path), beam_size=5)
|
||||
transcribed_text = " ".join([segment.text for segment in segments])
|
||||
|
||||
# Normalize texts for comparison
|
||||
original_text_normalized = normalize_text(original_text)
|
||||
transcribed_text_normalized = normalize_text(transcribed_text)
|
||||
|
||||
# Enhanced comparison using detailed fuzzy matching
|
||||
is_detailed_match = detailed_comparison(original_text_normalized, transcribed_text_normalized, args.threshold)
|
||||
has_spoken_punctuation = contains_spoken_punctuation(transcribed_text_normalized) and not contains_spoken_punctuation(original_text_normalized)
|
||||
|
||||
# Adjust is_match based on detailed comparison and spoken punctuation check
|
||||
is_match = is_detailed_match and not has_spoken_punctuation
|
||||
|
||||
# Only log and flag IDs for review if there's a mismatch or detected issues
|
||||
if not is_match:
|
||||
#print(f"\033[93mMismatch Detected - ID:\033[0m {item_id}")
|
||||
print(f"[AllTalk TTSDiff] \033[93mText:\033[0m {original_text}")
|
||||
print(f"[AllTalk TTSDiff] \033[91mTTS :\033[0m{transcribed_text}")
|
||||
if has_spoken_punctuation:
|
||||
print(f"[AllTalk TTSDiff] Note: Potential incorrect spoken punctuation detected.")
|
||||
flagged_ids.append(item_id) # Track the ID for review
|
||||
|
||||
def main():
|
||||
print(f"[AllTalk TTSDiff]")
|
||||
print(f"[AllTalk TTSDiff]")
|
||||
print("[AllTalk TTSDiff] \033[92mStarting Compare of Text vs TTS:\033[0m")
|
||||
print("[AllTalk TTSDiff]")
|
||||
print("[AllTalk TTSDiff] \033[94mJSON file :\033[92m", json_file_path, "\033[0m")
|
||||
print("[AllTalk TTSDiff] \033[94mWAV files :\033[92m", wav_file_path, "\033[0m")
|
||||
print("[AllTalk TTSDiff] \033[94mAccuracy :\033[92m", accuracy_threshold, "%", "\033[0m")
|
||||
detect_cublas()
|
||||
model_size = "large-v2"
|
||||
device = "cuda" if torch.cuda.is_available() else "cpu"
|
||||
model = WhisperModel(model_size, device=device, compute_type="float32")
|
||||
|
||||
flagged_ids = [] # Initialize the list to track IDs needing review
|
||||
|
||||
try:
|
||||
with open(json_file_path, "r", encoding="utf-8") as f:
|
||||
tts_list = json.load(f)
|
||||
except FileNotFoundError:
|
||||
print(f"[AllTalk TTSDiff] ERROR STARTING SCRIPT:")
|
||||
print("[AllTalk TTSDiff] Error: \033[93mttsList.json\033[0m file not found.")
|
||||
print("[AllTalk TTSDiff] Please ensure you follow these steps:")
|
||||
print("[AllTalk TTSDiff] After generating your text in the TTS Generator, you need to `Export List to JSON` and save the file in the")
|
||||
print("[AllTalk TTSDiff] same folder/directory this script is running from.")
|
||||
print("[AllTalk TTSDiff] The JSON file must be named \033[93mttsList.json\033[0m")
|
||||
exit(1)
|
||||
|
||||
print(f"[AllTalk TTSDiff]")
|
||||
|
||||
for item in tts_list:
|
||||
print(f"[AllTalk TTSDiff] Processing ID: {item['id']}")
|
||||
transcribe_and_compare(item['fileUrl'], item['text'], model, item['id'], flagged_ids)
|
||||
|
||||
print(f"[AllTalk TTSDiff]")
|
||||
# Print summary information at the end
|
||||
if flagged_ids:
|
||||
print(f"[AllTalk TTSDiff] \033[94mIDs needing review:\033[0m", ', '.join(map(str, flagged_ids)))
|
||||
print(f"[AllTalk TTSDiff]")
|
||||
print(f"[AllTalk TTSDiff] Review ID's and correct any lines by editing & regenerating as necessary.")
|
||||
else:
|
||||
print("[AllTalk TTSDiff] \033[94mIDs needing review:\033[0m No issues detected.")
|
||||
summary_data = {
|
||||
"flagged_ids": flagged_ids
|
||||
}
|
||||
with open(wav_file_path / "analysis_summary.json", "w") as summary_file:
|
||||
json.dump(summary_data, summary_file)
|
||||
print("[AllTalk TTSDiff]")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,179 @@
|
||||
export interface CrunkerConstructorOptions {
|
||||
/**
|
||||
* Sample rate for Crunker's internal audio context.
|
||||
*
|
||||
* @default 44100
|
||||
*/
|
||||
sampleRate: number;
|
||||
}
|
||||
export type CrunkerInputTypes = string | File | Blob;
|
||||
/**
|
||||
* An exported Crunker audio object.
|
||||
*/
|
||||
export interface ExportedCrunkerAudio {
|
||||
blob: Blob;
|
||||
url: string;
|
||||
element: HTMLAudioElement;
|
||||
}
|
||||
/**
|
||||
* Crunker is the simple way to merge, concatenate, play, export and download audio files using the Web Audio API.
|
||||
*/
|
||||
export default class Crunker {
|
||||
private readonly _sampleRate;
|
||||
private readonly _context;
|
||||
/**
|
||||
* Creates a new instance of Crunker with the provided options.
|
||||
*
|
||||
* If `sampleRate` is not defined, it will auto-select an appropriate sample rate
|
||||
* for the device being used.
|
||||
*/
|
||||
constructor({ sampleRate }?: Partial<CrunkerConstructorOptions>);
|
||||
/**
|
||||
* Creates Crunker's internal AudioContext.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
private _createContext;
|
||||
/**
|
||||
*
|
||||
* The internal AudioContext used by Crunker.
|
||||
*/
|
||||
get context(): AudioContext;
|
||||
/**
|
||||
* Asynchronously fetches multiple audio files and returns an array of AudioBuffers.
|
||||
*/
|
||||
fetchAudio(...filepaths: CrunkerInputTypes[]): Promise<AudioBuffer[]>;
|
||||
/**
|
||||
* Merges (layers) multiple AudioBuffers into a single AudioBuffer.
|
||||
*
|
||||
* **Visual representation:**
|
||||
*
|
||||
* 
|
||||
*/
|
||||
mergeAudio(buffers: AudioBuffer[]): AudioBuffer;
|
||||
/**
|
||||
* Concatenates multiple AudioBuffers into a single AudioBuffer.
|
||||
*
|
||||
* **Visual representation:**
|
||||
*
|
||||
* 
|
||||
*/
|
||||
concatAudio(buffers: AudioBuffer[]): AudioBuffer;
|
||||
/**
|
||||
* Pads a specified AudioBuffer with silence from a specified start time,
|
||||
* for a specified length of time.
|
||||
*
|
||||
* Accepts float values as well as whole integers.
|
||||
*
|
||||
* @param buffer AudioBuffer to pad
|
||||
* @param padStart Time to start padding (in seconds)
|
||||
* @param seconds Duration to pad for (in seconds)
|
||||
*/
|
||||
padAudio(buffer: AudioBuffer, padStart?: number, seconds?: number): AudioBuffer;
|
||||
/**
|
||||
* Slices an AudioBuffer from the specified start time to the end time, with optional fade in and out.
|
||||
*
|
||||
* @param buffer AudioBuffer to slice
|
||||
* @param start Start time (in seconds)
|
||||
* @param end End time (in seconds)
|
||||
* @param fadeIn Fade in duration (in seconds, default is 0)
|
||||
* @param fadeOut Fade out duration (in seconds, default is 0)
|
||||
*/
|
||||
sliceAudio(buffer: AudioBuffer, start: number, end: number, fadeIn?: number, fadeOut?: number): AudioBuffer;
|
||||
/**
|
||||
* Plays the provided AudioBuffer in an AudioBufferSourceNode.
|
||||
*/
|
||||
play(buffer: AudioBuffer): AudioBufferSourceNode;
|
||||
/**
|
||||
* Exports the specified AudioBuffer to a Blob, Object URI and HTMLAudioElement.
|
||||
*
|
||||
* Note that changing the MIME type does not change the actual file format. The
|
||||
* file format will **always** be a WAVE file due to how audio is stored in the
|
||||
* browser.
|
||||
*
|
||||
* @param buffer Buffer to export
|
||||
* @param type MIME type (default: `audio/wav`)
|
||||
*/
|
||||
export(buffer: AudioBuffer, type?: string): ExportedCrunkerAudio;
|
||||
/**
|
||||
* Downloads the provided Blob.
|
||||
*
|
||||
* @param blob Blob to download
|
||||
* @param filename An optional file name to use for the download (default: `crunker`)
|
||||
*/
|
||||
download(blob: Blob, filename?: string): HTMLAnchorElement;
|
||||
/**
|
||||
* Executes a callback if the browser does not support the Web Audio API.
|
||||
*
|
||||
* Returns the result of the callback, or `undefined` if the Web Audio API is supported.
|
||||
*
|
||||
* @param callback callback to run if the browser does not support the Web Audio API
|
||||
*/
|
||||
notSupported<T>(callback: () => T): T | undefined;
|
||||
/**
|
||||
* Closes Crunker's internal AudioContext.
|
||||
*/
|
||||
close(): this;
|
||||
/**
|
||||
* Returns the largest duration of the longest AudioBuffer.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
private _maxDuration;
|
||||
/**
|
||||
* Returns the largest number of channels in an array of AudioBuffers.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
private _maxNumberOfChannels;
|
||||
/**
|
||||
* Returns the sum of the lengths of an array of AudioBuffers.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
private _totalLength;
|
||||
/**
|
||||
* Returns whether the browser supports the Web Audio API.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
private _isSupported;
|
||||
/**
|
||||
* Writes the WAV headers for the specified Float32Array.
|
||||
*
|
||||
* Returns a DataView containing the WAV headers and file content.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
private _writeHeaders;
|
||||
/**
|
||||
* Converts a Float32Array to 16-bit PCM.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
private _floatTo16BitPCM;
|
||||
/**
|
||||
* Writes a string to a DataView at the specified offset.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
private _writeString;
|
||||
/**
|
||||
* Converts an AudioBuffer to a Float32Array.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
private _interleave;
|
||||
/**
|
||||
* Creates an HTMLAudioElement whose source is the specified Blob.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
private _renderAudioElement;
|
||||
/**
|
||||
* Creates an Object URL for the specified Blob.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
private _renderURL;
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
var e={d:(t,n)=>{for(var r in n)e.o(n,r)&&!e.o(t,r)&&Object.defineProperty(t,r,{enumerable:!0,get:n[r]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t)},t={};function n(e){return n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},n(e)}function r(e){return function(e){if(Array.isArray(e))return a(e)}(e)||function(e){if("undefined"!=typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}(e)||function(e,t){if(!e)return;if("string"==typeof e)return a(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);"Object"===n&&e.constructor&&(n=e.constructor.name);if("Map"===n||"Set"===n)return Array.from(e);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return a(e,t)}(e)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function a(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n<t;n++)r[n]=e[n];return r}function o(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function i(e,t){for(var r=0;r<t.length;r++){var a=t[r];a.enumerable=a.enumerable||!1,a.configurable=!0,"value"in a&&(a.writable=!0),Object.defineProperty(e,(o=a.key,i=void 0,i=function(e,t){if("object"!==n(e)||null===e)return e;var r=e[Symbol.toPrimitive];if(void 0!==r){var a=r.call(e,t||"default");if("object"!==n(a))return a;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(o,"string"),"symbol"===n(i)?i:String(i)),a)}var o,i}e.d(t,{Z:()=>u});var u=function(){function e(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=t.sampleRate;o(this,e),this._context=this._createContext(n),n||(n=this._context.sampleRate),this._sampleRate=n}var t,n,a;return t=e,n=[{key:"_createContext",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:44100;return window.AudioContext=window.AudioContext||window.webkitAudioContext||window.mozAudioContext,new AudioContext({sampleRate:e})}},{key:"context",get:function(){return this._context}},{key:"fetchAudio",value:async function(){for(var e=this,t=arguments.length,n=new Array(t),r=0;r<t;r++)n[r]=arguments[r];return await Promise.all(n.map((async function(t){var n;return n=t instanceof File||t instanceof Blob?await t.arrayBuffer():await fetch(t).then((function(e){return e.headers.has("Content-Type")&&!e.headers.get("Content-Type").includes("audio/")&&console.warn("Crunker: Attempted to fetch an audio file, but its MIME type is `".concat(e.headers.get("Content-Type").split(";")[0],"`. We'll try and continue anyway. (file: \"").concat(t,'")')),e.arrayBuffer()})),await e._context.decodeAudioData(n)})))}},{key:"mergeAudio",value:function(e){var t=this._context.createBuffer(this._maxNumberOfChannels(e),this._sampleRate*this._maxDuration(e),this._sampleRate);return e.forEach((function(e){for(var n=0;n<e.numberOfChannels;n++){for(var r=t.getChannelData(n),a=e.getChannelData(n),o=e.getChannelData(n).length-1;o>=0;o--)r[o]+=a[o];t.getChannelData(n).set(r)}})),t}},{key:"concatAudio",value:function(e){var t=this._context.createBuffer(this._maxNumberOfChannels(e),this._totalLength(e),this._sampleRate),n=0;return e.forEach((function(e){for(var r=0;r<e.numberOfChannels;r++)t.getChannelData(r).set(e.getChannelData(r),n);n+=e.length})),t}},{key:"padAudio",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0;if(0===n)return e;if(t<0)throw new Error('Crunker: Parameter "padStart" in padAudio must be positive');if(n<0)throw new Error('Crunker: Parameter "seconds" in padAudio must be positive');for(var r=this._context.createBuffer(e.numberOfChannels,Math.ceil(e.length+n*e.sampleRate),e.sampleRate),a=0;a<e.numberOfChannels;a++){var o=e.getChannelData(a);r.getChannelData(a).set(o.subarray(0,Math.ceil(t*e.sampleRate)+1),0),r.getChannelData(a).set(o.subarray(Math.ceil(t*e.sampleRate)+2,r.length+1),Math.ceil((t+n)*e.sampleRate))}return r}},{key:"sliceAudio",value:function(e,t,n){var r=arguments.length>3&&void 0!==arguments[3]?arguments[3]:0,a=arguments.length>4&&void 0!==arguments[4]?arguments[4]:0;if(t>=n)throw new Error('Crunker: "start" time should be less than "end" time in sliceAudio method');for(var o=Math.round((n-t)*this._sampleRate),i=Math.round(t*this._sampleRate),u=this._context.createBuffer(e.numberOfChannels,o,this._sampleRate),l=0;l<e.numberOfChannels;l++)for(var s=e.getChannelData(l),c=u.getChannelData(l),f=0;f<o;f++)c[f]=s[i+f],f<r*this._sampleRate&&(c[f]*=f/(r*this._sampleRate)),f>o-a*this._sampleRate&&(c[f]*=(o-f)/(a*this._sampleRate));return u}},{key:"play",value:function(e){var t=this._context.createBufferSource();return t.buffer=e,t.connect(this._context.destination),t.start(),Line truncated
|
||||
//# sourceMappingURL=crunker.esm.js.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"crunker.esm.js","mappings":"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 truncated
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
@@ -0,0 +1,4 @@
|
||||
/*! howler.js v2.2.4 | (c) 2013-2020, James Simpson of GoldFire Studios | MIT License | howlerjs.com */
|
||||
!function(){"use strict";var e=function(){this.init()};e.prototype={init:function(){var e=this||n;return e._counter=1e3,e._html5AudioPool=[],e.html5PoolSize=10,e._codecs={},e._howls=[],e._muted=!1,e._volume=1,e._canPlayEvent="canplaythrough",e._navigator="undefined"!=typeof window&&window.navigator?window.navigator:null,e.masterGain=null,e.noAudio=!1,e.usingWebAudio=!0,e.autoSuspend=!0,e.ctx=null,e.autoUnlock=!0,e._setup(),e},volume:function(e){var o=this||n;if(e=parseFloat(e),o.ctx||_(),void 0!==e&&e>=0&&e<=1){if(o._volume=e,o._muted)return o;o.usingWebAudio&&o.masterGain.gain.setValueAtTime(e,n.ctx.currentTime);for(var t=0;t<o._howls.length;t++)if(!o._howls[t]._webAudio)for(var r=o._howls[t]._getSoundIds(),a=0;a<r.length;a++){var u=o._howls[t]._soundById(r[a]);u&&u._node&&(u._node.volume=u._volume*e)}return o}return o._volume},mute:function(e){var o=this||n;o.ctx||_(),o._muted=e,o.usingWebAudio&&o.masterGain.gain.setValueAtTime(e?0:o._volume,n.ctx.currentTime);for(var t=0;t<o._howls.length;t++)if(!o._howls[t]._webAudio)for(var r=o._howls[t]._getSoundIds(),a=0;a<r.length;a++){var u=o._howls[t]._soundById(r[a]);u&&u._node&&(u._node.muted=!!e||u._muted)}return o},stop:function(){for(var e=this||n,o=0;o<e._howls.length;o++)e._howls[o].stop();return e},unload:function(){for(var e=this||n,o=e._howls.length-1;o>=0;o--)e._howls[o].unload();return e.usingWebAudio&&e.ctx&&void 0!==e.ctx.close&&(e.ctx.close(),e.ctx=null,_()),e},codecs:function(e){return(this||n)._codecs[e.replace(/^x-/,"")]},_setup:function(){var e=this||n;if(e.state=e.ctx?e.ctx.state||"suspended":"suspended",e._autoSuspend(),!e.usingWebAudio)if("undefined"!=typeof Audio)try{var o=new Audio;void 0===o.oncanplaythrough&&(e._canPlayEvent="canplay")}catch(n){e.noAudio=!0}else e.noAudio=!0;try{var o=new Audio;o.muted&&(e.noAudio=!0)}catch(e){}return e.noAudio||e._setupCodecs(),e},_setupCodecs:function(){var e=this||n,o=null;try{o="undefined"!=typeof Audio?new Audio:null}catch(n){return e}if(!o||"function"!=typeof o.canPlayType)return e;var t=o.canPlayType("audio/mpeg;").replace(/^no$/,""),r=e._navigator?e._navigator.userAgent:"",a=r.match(/OPR\/(\d+)/g),u=a&&parseInt(a[0].split("/")[1],10)<33,d=-1!==r.indexOf("Safari")&&-1===r.indexOf("Chrome"),i=r.match(/Version\/(.*?) /),_=d&&i&&parseInt(i[1],10)<15;return e._codecs={mp3:!(u||!t&&!o.canPlayType("audio/mp3;").replace(/^no$/,"")),mpeg:!!t,opus:!!o.canPlayType('audio/ogg; codecs="opus"').replace(/^no$/,""),ogg:!!o.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/,""),oga:!!o.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/,""),wav:!!(o.canPlayType('audio/wav; codecs="1"')||o.canPlayType("audio/wav")).replace(/^no$/,""),aac:!!o.canPlayType("audio/aac;").replace(/^no$/,""),caf:!!o.canPlayType("audio/x-caf;").replace(/^no$/,""),m4a:!!(o.canPlayType("audio/x-m4a;")||o.canPlayType("audio/m4a;")||o.canPlayType("audio/aac;")).replace(/^no$/,""),m4b:!!(o.canPlayType("audio/x-m4b;")||o.canPlayType("audio/m4b;")||o.canPlayType("audio/aac;")).replace(/^no$/,""),mp4:!!(o.canPlayType("audio/x-mp4;")||o.canPlayType("audio/mp4;")||o.canPlayType("audio/aac;")).replace(/^no$/,""),weba:!(_||!o.canPlayType('audio/webm; codecs="vorbis"').replace(/^no$/,"")),webm:!(_||!o.canPlayType('audio/webm; codecs="vorbis"').replace(/^no$/,"")),dolby:!!o.canPlayType('audio/mp4; codecs="ec-3"').replace(/^no$/,""),flac:!!(o.canPlayType("audio/x-flac;")||o.canPlayType("audio/flac;")).replace(/^no$/,"")},e},_unlockAudio:function(){var e=this||n;if(!e._audioUnlocked&&e.ctx){e._audioUnlocked=!1,e.autoUnlock=!1,e._mobileUnloaded||44100===e.ctx.sampleRate||(e._mobileUnloaded=!0,e.unload()),e._scratchBuffer=e.ctx.createBuffer(1,1,22050);var o=function(n){for(;e._html5AudioPool.length<e.html5PoolSize;)try{var t=new Audio;t._unlocked=!0,e._releaseHtml5Audio(t)}catch(n){e.noAudio=!0;break}for(var r=0;r<e._howls.length;r++)if(!e._howls[r]._webAudio)for(var a=e._howls[r]._getSoundIds(),u=0;u<a.length;u++){var d=e._howls[r]._soundById(a[u]);d&&d._node&&!d._node._unlocked&&(d._node._unlocked=!0,d._node.load())}e._autoResume();var i=e.ctx.createBufferSource();i.buffer=e._scratchBuffer,i.connect(e.ctx.destination),void 0===i.start?i.noteOn(0):i.start(0),"function"==typeof e.ctx.resume&&e.ctx.resume(),i.onended=function(){i.disconnect(0),e._audioUnlocked=!0,document.removeEventListener("touchstart",o,!0),document.removeEventListener("touchend",o,!0),document.removeEventListener("click",o,!0),document.removeEventListener("keydown",o,!0);for(var n=0;n<e._howls.length;n++)e._howls[n]._emit("unlock")}};return document.addEventListener("touchstart",o,!0),document.addEventListener("touchend",o,!0),document.addEventListener("click",o,!0),document.addEventListener("keydown",o,!0),e}},_obtainHtml5Audio:function(){var e=this||n;if(e._html5AudioPool.length)return e._html5AudioPool.pop();var o=(new Audio).play();return o&&"undefined"!=typeof Promise&&(o instanceof Promise||"function"==typeof o.then)&&o.catch(function(){console.warn("HTML5 Audio pool eLine truncated
|
||||
/*! Spatial Plugin */
|
||||
!function(){"use strict";HowlerGlobal.prototype._pos=[0,0,0],HowlerGlobal.prototype._orientation=[0,0,-1,0,1,0],HowlerGlobal.prototype.stereo=function(e){var n=this;if(!n.ctx||!n.ctx.listener)return n;for(var t=n._howls.length-1;t>=0;t--)n._howls[t].stereo(e);return n},HowlerGlobal.prototype.pos=function(e,n,t){var r=this;return r.ctx&&r.ctx.listener?(n="number"!=typeof n?r._pos[1]:n,t="number"!=typeof t?r._pos[2]:t,"number"!=typeof e?r._pos:(r._pos=[e,n,t],void 0!==r.ctx.listener.positionX?(r.ctx.listener.positionX.setTargetAtTime(r._pos[0],Howler.ctx.currentTime,.1),r.ctx.listener.positionY.setTargetAtTime(r._pos[1],Howler.ctx.currentTime,.1),r.ctx.listener.positionZ.setTargetAtTime(r._pos[2],Howler.ctx.currentTime,.1)):r.ctx.listener.setPosition(r._pos[0],r._pos[1],r._pos[2]),r)):r},HowlerGlobal.prototype.orientation=function(e,n,t,r,o,i){var a=this;if(!a.ctx||!a.ctx.listener)return a;var p=a._orientation;return n="number"!=typeof n?p[1]:n,t="number"!=typeof t?p[2]:t,r="number"!=typeof r?p[3]:r,o="number"!=typeof o?p[4]:o,i="number"!=typeof i?p[5]:i,"number"!=typeof e?p:(a._orientation=[e,n,t,r,o,i],void 0!==a.ctx.listener.forwardX?(a.ctx.listener.forwardX.setTargetAtTime(e,Howler.ctx.currentTime,.1),a.ctx.listener.forwardY.setTargetAtTime(n,Howler.ctx.currentTime,.1),a.ctx.listener.forwardZ.setTargetAtTime(t,Howler.ctx.currentTime,.1),a.ctx.listener.upX.setTargetAtTime(r,Howler.ctx.currentTime,.1),a.ctx.listener.upY.setTargetAtTime(o,Howler.ctx.currentTime,.1),a.ctx.listener.upZ.setTargetAtTime(i,Howler.ctx.currentTime,.1)):a.ctx.listener.setOrientation(e,n,t,r,o,i),a)},Howl.prototype.init=function(e){return function(n){var t=this;return t._orientation=n.orientation||[1,0,0],t._stereo=n.stereo||null,t._pos=n.pos||null,t._pannerAttr={coneInnerAngle:void 0!==n.coneInnerAngle?n.coneInnerAngle:360,coneOuterAngle:void 0!==n.coneOuterAngle?n.coneOuterAngle:360,coneOuterGain:void 0!==n.coneOuterGain?n.coneOuterGain:0,distanceModel:void 0!==n.distanceModel?n.distanceModel:"inverse",maxDistance:void 0!==n.maxDistance?n.maxDistance:1e4,panningModel:void 0!==n.panningModel?n.panningModel:"HRTF",refDistance:void 0!==n.refDistance?n.refDistance:1,rolloffFactor:void 0!==n.rolloffFactor?n.rolloffFactor:1},t._onstereo=n.onstereo?[{fn:n.onstereo}]:[],t._onpos=n.onpos?[{fn:n.onpos}]:[],t._onorientation=n.onorientation?[{fn:n.onorientation}]:[],e.call(this,n)}}(Howl.prototype.init),Howl.prototype.stereo=function(n,t){var r=this;if(!r._webAudio)return r;if("loaded"!==r._state)return r._queue.push({event:"stereo",action:function(){r.stereo(n,t)}}),r;var o=void 0===Howler.ctx.createStereoPanner?"spatial":"stereo";if(void 0===t){if("number"!=typeof n)return r._stereo;r._stereo=n,r._pos=[n,0,0]}for(var i=r._getSoundIds(t),a=0;a<i.length;a++){var p=r._soundById(i[a]);if(p){if("number"!=typeof n)return p._stereo;p._stereo=n,p._pos=[n,0,0],p._node&&(p._pannerAttr.panningModel="equalpower",p._panner&&p._panner.pan||e(p,o),"spatial"===o?void 0!==p._panner.positionX?(p._panner.positionX.setValueAtTime(n,Howler.ctx.currentTime),p._panner.positionY.setValueAtTime(0,Howler.ctx.currentTime),p._panner.positionZ.setValueAtTime(0,Howler.ctx.currentTime)):p._panner.setPosition(n,0,0):p._panner.pan.setValueAtTime(n,Howler.ctx.currentTime)),r._emit("stereo",p._id)}}return r},Howl.prototype.pos=function(n,t,r,o){var i=this;if(!i._webAudio)return i;if("loaded"!==i._state)return i._queue.push({event:"pos",action:function(){i.pos(n,t,r,o)}}),i;if(t="number"!=typeof t?0:t,r="number"!=typeof r?-.5:r,void 0===o){if("number"!=typeof n)return i._pos;i._pos=[n,t,r]}for(var a=i._getSoundIds(o),p=0;p<a.length;p++){var s=i._soundById(a[p]);if(s){if("number"!=typeof n)return s._pos;s._pos=[n,t,r],s._node&&(s._panner&&!s._panner.pan||e(s,"spatial"),void 0!==s._panner.positionX?(s._panner.positionX.setValueAtTime(n,Howler.ctx.currentTime),s._panner.positionY.setValueAtTime(t,Howler.ctx.currentTime),s._panner.positionZ.setValueAtTime(r,Howler.ctx.currentTime)):s._panner.setPosition(n,t,r)),i._emit("pos",s._id)}}return i},Howl.prototype.orientation=function(n,t,r,o){var i=this;if(!i._webAudio)return i;if("loaded"!==i._state)return i._queue.push({event:"orientation",action:function(){i.orientation(n,t,r,o)}}),i;if(t="number"!=typeof t?i._orientation[1]:t,r="number"!=typeof r?i._orientation[2]:r,void 0===o){if("number"!=typeof n)return i._orientation;i._orientation=[n,t,r]}for(var a=i._getSoundIds(o),p=0;p<a.length;p++){var s=i._soundById(a[p]);if(s){if("number"!=typeof n)return s._orientation;s._orientation=[n,t,r],s._node&&(s._panner||(s._pos||(s._pos=i._pos||[0,0,-.5]),e(s,"spatial")),void 0!==s._panner.orientationX?(s._panner.orientationX.setValueAtTime(n,Howler.ctx.currentTime),s._panner.orientationY.setValueAtTime(t,Howler.ctx.currentTime),s._panner.orientationZ.setValueAtTime(r,Howler.ctx.currentTime)):s._panner.setOrientation(n,t,r)),i._emit("orientation",s._id)}}return i},Howl.prototype.pannerAttr=function(){var n,t,r,o=this,i=arguments;if(!o._webAudioLine truncated
|
||||
@@ -0,0 +1,77 @@
|
||||
import json
|
||||
import argparse
|
||||
import soundfile as sf
|
||||
from pathlib import Path
|
||||
|
||||
parser = argparse.ArgumentParser(description="Compare TTS output with the original text using detailed comparison.")
|
||||
parser.add_argument("--ttslistpath", help="Path to the ttsList.json file")
|
||||
parser.add_argument("--wavfilespath", help="Path to the wav outputs folder")
|
||||
args = parser.parse_args()
|
||||
|
||||
if not args.ttslistpath:
|
||||
parser.error("[AllTalk TTSSRT] Please specify the path to the ttslist.json file using the --ttslistpath argument.")
|
||||
if not args.wavfilespath:
|
||||
parser.error("[AllTalk TTSSRT] Please specify the path to the wavs output folder file using the --wavfilespath argument.")
|
||||
|
||||
json_file_path = Path(args.ttslistpath).resolve()
|
||||
audio_files_base_path = Path(args.wavfilespath).resolve()
|
||||
|
||||
print(f"[AllTalk TTSSRT]")
|
||||
print("[AllTalk TTSSRT] \033[92mStarting SRT Subtitle generation:\033[0m")
|
||||
print("[AllTalk TTSSRT]")
|
||||
print("[AllTalk TTSSRT] \033[94mJSON file :\033[92m", json_file_path, "\033[0m")
|
||||
print("[AllTalk TTSSRT] \033[94mWAV files :\033[92m", audio_files_base_path, "\033[0m")
|
||||
print("[AllTalk TTSSRT]")
|
||||
|
||||
# Function to convert time in seconds to SRT time format
|
||||
def format_srt_time(seconds):
|
||||
hours = int(seconds // 3600)
|
||||
minutes = int((seconds % 3600) // 60)
|
||||
seconds = seconds % 60
|
||||
milliseconds = int((seconds - int(seconds)) * 1000)
|
||||
return f"{hours:02}:{minutes:02}:{int(seconds):02},{milliseconds:03}"
|
||||
|
||||
# Load the JSON data
|
||||
with open(json_file_path, 'r') as json_file:
|
||||
data = json.load(json_file)
|
||||
|
||||
# Initialize start time and SRT lines
|
||||
start_time = 0.0
|
||||
srt_lines = []
|
||||
|
||||
# Loop through the JSON data to build SRT entries
|
||||
for entry in data:
|
||||
file_name = Path(entry['fileUrl']).name # Get the file name from the URL
|
||||
file_path = audio_files_base_path / file_name
|
||||
print(f"[AllTalk TTSSRT] Processing file: {file_name}")
|
||||
|
||||
if not file_path.exists():
|
||||
print(f"[AllTalk TTSSRT] Audio file does not exist: {file_path}")
|
||||
continue
|
||||
|
||||
try:
|
||||
# Use soundfile to read the duration of the WAV file
|
||||
with sf.SoundFile(str(file_path), 'r') as f:
|
||||
duration = len(f) / f.samplerate
|
||||
end_time = start_time + duration
|
||||
|
||||
# Format the SRT entry
|
||||
start_timestamp = format_srt_time(start_time)
|
||||
end_timestamp = format_srt_time(end_time)
|
||||
srt_lines.append(f"{len(srt_lines)+1}\n{start_timestamp} --> {end_timestamp}\n{entry['text']}\n")
|
||||
|
||||
# Update the start time for the next entry
|
||||
start_time = end_time
|
||||
except RuntimeError as e:
|
||||
print(f"[AllTalk TTSSRT] Error reading {file_path}: {e}")
|
||||
|
||||
# Join all SRT lines into the final SRT content
|
||||
srt_content = "\n".join(srt_lines)
|
||||
|
||||
# Save the SRT content to a file
|
||||
srt_file_path = audio_files_base_path / "subtitles.srt"
|
||||
with open(srt_file_path, "w") as srt_file:
|
||||
srt_file.write(srt_content)
|
||||
|
||||
print("[AllTalk TTSSRT]")
|
||||
print(f"[AllTalk TTSSRT] \033[94mSRT file created at \033[0m{srt_file_path}")
|
||||
@@ -0,0 +1,2 @@
|
||||
/*! For license information please see 1995fcd6d39cade7d871.js.LICENSE.txt */
|
||||
function _typeof(t){return _typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},_typeof(t)}function _regeneratorRuntime(){"use strict";_regeneratorRuntime=function(){return e};var t,e={},r=Object.prototype,n=r.hasOwnProperty,o=Object.defineProperty||function(t,e,r){t[e]=r.value},i="function"==typeof Symbol?Symbol:{},a=i.iterator||"@@iterator",c=i.asyncIterator||"@@asyncIterator",u=i.toStringTag||"@@toStringTag";function l(t,e,r){return Object.defineProperty(t,e,{value:r,enumerable:!0,configurable:!0,writable:!0}),t[e]}try{l({},"")}catch(t){l=function(t,e,r){return t[e]=r}}function f(t,e,r,n){var i=e&&e.prototype instanceof m?e:m,a=Object.create(i.prototype),c=new G(n||[]);return o(a,"_invoke",{value:S(t,r,c)}),a}function s(t,e,r){try{return{type:"normal",arg:t.call(e,r)}}catch(t){return{type:"throw",arg:t}}}e.wrap=f;var h="suspendedStart",p="suspendedYield",y="executing",d="completed",v={};function m(){}function g(){}function w(){}var x={};l(x,a,(function(){return this}));var E=Object.getPrototypeOf,b=E&&E(E(B([])));b&&b!==r&&n.call(b,a)&&(x=b);var T=w.prototype=m.prototype=Object.create(x);function _(t){["next","throw","return"].forEach((function(e){l(t,e,(function(t){return this._invoke(e,t)}))}))}function L(t,e){function r(o,i,a,c){var u=s(t[o],t,i);if("throw"!==u.type){var l=u.arg,f=l.value;return f&&"object"==_typeof(f)&&n.call(f,"__await")?e.resolve(f.__await).then((function(t){r("next",t,a,c)}),(function(t){r("throw",t,a,c)})):e.resolve(f).then((function(t){l.value=t,a(l)}),(function(t){return r("throw",t,a,c)}))}c(u.arg)}var i;o(this,"_invoke",{value:function(t,n){function o(){return new e((function(e,o){r(t,n,e,o)}))}return i=i?i.then(o,o):o()}})}function S(e,r,n){var o=h;return function(i,a){if(o===y)throw new Error("Generator is already running");if(o===d){if("throw"===i)throw a;return{value:t,done:!0}}for(n.method=i,n.arg=a;;){var c=n.delegate;if(c){var u=I(c,n);if(u){if(u===v)continue;return u}}if("next"===n.method)n.sent=n._sent=n.arg;else if("throw"===n.method){if(o===h)throw o=d,n.arg;n.dispatchException(n.arg)}else"return"===n.method&&n.abrupt("return",n.arg);o=y;var l=s(e,r,n);if("normal"===l.type){if(o=n.done?d:p,l.arg===v)continue;return{value:l.arg,done:n.done}}"throw"===l.type&&(o=d,n.method="throw",n.arg=l.arg)}}}function I(e,r){var n=r.method,o=e.iterator[n];if(o===t)return r.delegate=null,"throw"===n&&e.iterator.return&&(r.method="return",r.arg=t,I(e,r),"throw"===r.method)||"return"!==n&&(r.method="throw",r.arg=new TypeError("The iterator does not provide a '"+n+"' method")),v;var i=s(o,e.iterator,r.arg);if("throw"===i.type)return r.method="throw",r.arg=i.arg,r.delegate=null,v;var a=i.arg;return a?a.done?(r[e.resultName]=a.value,r.next=e.nextLoc,"return"!==r.method&&(r.method="next",r.arg=t),r.delegate=null,v):a:(r.method="throw",r.arg=new TypeError("iterator result is not an object"),r.delegate=null,v)}function O(t){var e={tryLoc:t[0]};1 in t&&(e.catchLoc=t[1]),2 in t&&(e.finallyLoc=t[2],e.afterLoc=t[3]),this.tryEntries.push(e)}function j(t){var e=t.completion||{};e.type="normal",delete e.arg,t.completion=e}function G(t){this.tryEntries=[{tryLoc:"root"}],t.forEach(O,this),this.reset(!0)}function B(e){if(e||""===e){var r=e[a];if(r)return r.call(e);if("function"==typeof e.next)return e;if(!isNaN(e.length)){var o=-1,i=function r(){for(;++o<e.length;)if(n.call(e,o))return r.value=e[o],r.done=!1,r;return r.value=t,r.done=!0,r};return i.next=i}}throw new TypeError(_typeof(e)+" is not iterable")}return g.prototype=w,o(T,"constructor",{value:w,configurable:!0}),o(w,"constructor",{value:g,configurable:!0}),g.displayName=l(w,u,"GeneratorFunction"),e.isGeneratorFunction=function(t){var e="function"==typeof t&&t.constructor;return!!e&&(e===g||"GeneratorFunction"===(e.displayName||e.name))},e.mark=function(t){return Object.setPrototypeOf?Object.setPrototypeOf(t,w):(t.__proto__=w,l(t,u,"GeneratorFunction")),t.prototype=Object.create(T),t},e.awrap=function(t){return{__await:t}},_(L.prototype),l(L.prototype,c,(function(){return this})),e.AsyncIterator=L,e.async=function(t,r,n,o,i){void 0===i&&(i=Promise);var a=new L(f(t,r,n,o),i);return e.isGeneratorFunction(r)?a:a.next().then((function(t){return t.done?t.value:a.next()}))},_(T),l(T,u,"Generator"),l(T,a,(function(){return this})),l(T,"toString",(function(){return"[object Generator]"})),e.keys=function(t){var e=Object(t),r=[];for(var n in e)r.push(n);return r.reverse(),function t(){for(;r.length;){var n=r.pop();if(n in e)return t.value=n,t.done=!1,t}return t.done=!0,t}},e.values=B,G.prototype={constructor:G,reset:function(e){if(this.prev=0,this.next=0,this.sent=this._sent=t,this.done=!1,this.delegate=null,this.method="next",this.arg=t,this.tryEntries.forEach(j),!e)for(var r in this)"t"===r.charAt(0)&&n.call(this,r)&&!isNaN(+r.slice(1))&&(this[r]=t)},stop:function(){this.done=!0;var t=this.tryELine truncated
|
||||
@@ -0,0 +1 @@
|
||||
/*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
|
||||
* See LICENSE in the project root for license information.
|
||||
*/
|
||||
|
||||
html,
|
||||
body {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
ul {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.ms-welcome__header {
|
||||
padding: 20px;
|
||||
padding-bottom: 30px;
|
||||
padding-top: 100px;
|
||||
display: -webkit-flex;
|
||||
display: flex;
|
||||
-webkit-flex-direction: column;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.ms-welcome__main {
|
||||
display: -webkit-flex;
|
||||
display: flex;
|
||||
-webkit-flex-direction: column;
|
||||
flex-direction: column;
|
||||
-webkit-flex-wrap: nowrap;
|
||||
flex-wrap: nowrap;
|
||||
-webkit-align-items: center;
|
||||
align-items: center;
|
||||
-webkit-flex: 1 0 0;
|
||||
flex: 1 0 0;
|
||||
padding: 10px 20px;
|
||||
}
|
||||
|
||||
.ms-welcome__main > h2 {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.ms-welcome__features {
|
||||
list-style-type: none;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.ms-welcome__features.ms-List .ms-ListItem {
|
||||
padding-bottom: 20px;
|
||||
display: -webkit-flex;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.ms-welcome__features.ms-List .ms-ListItem > .ms-Icon {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.ms-welcome__action.ms-Button--hero {
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
.ms-Button.ms-Button--hero .ms-Button-label {
|
||||
color: #0078d7;
|
||||
}
|
||||
|
||||
.ms-Button.ms-Button--hero:hover .ms-Button-label,
|
||||
.ms-Button.ms-Button--hero:focus .ms-Button-label{
|
||||
color: #005a9e;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
b {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
After Width: | Height: | Size: 30 KiB |
|
After Width: | Height: | Size: 839 B |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 8.8 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 99 KiB |
@@ -0,0 +1 @@
|
||||
<!doctype html><html><head><meta charset="UTF-8"/><meta http-equiv="X-UA-Compatible" content="IE=Edge"/><script src="https://appsforoffice.microsoft.com/lib/1.1/hosted/office.js"></script><script defer="defer" src="polyfill.js"></script><script defer="defer" src="commands.js"></script></head><body></body></html>
|
||||
@@ -0,0 +1,2 @@
|
||||
!function(){var e={};e.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),Office.onReady((function(){})),("undefined"!=typeof self?self:"undefined"!=typeof window?window:void 0!==e.g?e.g:void 0).action=function(e){var n={type:Office.MailboxEnums.ItemNotificationMessageType.InformationalMessage,message:"Performed action.",icon:"Icon.80x80",persistent:!0};Office.context.mailbox.item.notificationMessages.replaceAsync("action",n),e.completed()}}();
|
||||
//# sourceMappingURL=commands.js.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"commands.js","mappings":"YACA,IAAIA,EAAsB,CAAC,ECD3BA,EAAoBC,EAAI,WACvB,GAA0B,iBAAfC,WAAyB,OAAOA,WAC3C,IACC,OAAOC,MAAQ,IAAIC,SAAS,cAAb,EAChB,CAAE,MAAOC,GACR,GAAsB,iBAAXC,OAAqB,OAAOA,MACxC,CACA,CAPuB,GCOxBC,OAAOC,SAAQ,WACb,KAuBuB,oBAATC,KACVA,KACkB,oBAAXH,OACPA,YACkB,IAAXI,EAAAA,EACPA,EAAAA,OACAC,GAMJC,OA5BF,SAAgBC,GACd,IAAMC,EAAU,CACdC,KAAMR,OAAOS,aAAaC,4BAA4BC,qBACtDJ,QAAS,oBACTK,KAAM,aACNC,YAAY,GAIdb,OAAOc,QAAQC,QAAQC,KAAKC,qBAAqBC,aAAa,SAAUX,GAGxED,EAAMa,WACR,C","sources":["webpack://office-addin-taskpane-js/webpack/bootstrap","webpack://office-addin-taskpane-js/webpack/runtime/global","webpack://office-addin-taskpane-js/./src/commands/commands.js"],"sourcesContent":["// The require scope\nvar __webpack_require__ = {};\n\n","__webpack_require__.g = (function() {\n\tif (typeof globalThis === 'object') return globalThis;\n\ttry {\n\t\treturn this || new Function('return this')();\n\t} catch (e) {\n\t\tif (typeof window === 'object') return window;\n\t}\n})();","/*\n * Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n * See LICENSE in the project root for license information.\n */\n\n/* global global, Office, self, window */\n\nOffice.onReady(() => {\n // If needed, Office.js is ready to be called\n});\n\n/**\n * Shows a notification when the add-in command is executed.\n * @param event {Office.AddinCommands.Event}\n */\nfunction action(event) {\n const message = {\n type: Office.MailboxEnums.ItemNotificationMessageType.InformationalMessage,\n message: \"Performed action.\",\n icon: \"Icon.80x80\",\n persistent: true,\n };\n\n // Show a notification message\n Office.context.mailbox.item.notificationMessages.replaceAsync(\"action\", message);\n\n // Be sure to indicate when the add-in command function is complete\n event.completed();\n}\n\nfunction getGlobal() {\n return typeof self !== \"undefined\"\n ? self\n : typeof window !== \"undefined\"\n ? window\n : typeof global !== \"undefined\"\n ? global\n : undefined;\n}\n\nconst g = getGlobal();\n\n// The add-in command functions need to be available in global scope\ng.action = action;\n"],"names":["__webpack_require__","g","globalThis","this","Function","e","window","Office","onReady","self","global","undefined","action","event","message","type","MailboxEnums","ItemNotificationMessageType","InformationalMessage","icon","persistent","context","mailbox","item","notificationMessages","replaceAsync","completed"],"sourceRoot":""}
|
||||
@@ -0,0 +1,79 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<OfficeApp xmlns="http://schemas.microsoft.com/office/appforoffice/1.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:bt="http://schemas.microsoft.com/office/officeappbasictypes/1.0" xmlns:ov="http://schemas.microsoft.com/office/taskpaneappversionoverrides" xsi:type="TaskPaneApp">
|
||||
<Id>68b6ad53-4f72-42a8-a971-a9643c2f409a</Id>
|
||||
<Version>1.0.0.0</Version>
|
||||
<ProviderName>AllTalk</ProviderName>
|
||||
<DefaultLocale>en-US</DefaultLocale>
|
||||
<DisplayName DefaultValue="AllTalk TTS"/>
|
||||
<Description DefaultValue="Enhance your document creation with AllTalk TTS's advanced text-to-voice functionality. Requires connection to AllTalk server."/>
|
||||
<IconUrl DefaultValue="http://127.0.0.1:7851/api/word_addin/assets/icon-32.png"/>
|
||||
<HighResolutionIconUrl DefaultValue="http://127.0.0.1:7851/api/word_addin/assets/icon-64.png"/>
|
||||
<SupportUrl DefaultValue="https://github.com/erew123/alltalk_tts/issues"/>
|
||||
<AppDomains>
|
||||
<AppDomain>https://www.contoso.com</AppDomain>
|
||||
</AppDomains>
|
||||
<Hosts>
|
||||
<Host Name="Document"/>
|
||||
</Hosts>
|
||||
<DefaultSettings>
|
||||
<SourceLocation DefaultValue="http://127.0.0.1:7851/api/word_addin/taskpane.html"/>
|
||||
</DefaultSettings>
|
||||
<Permissions>ReadWriteDocument</Permissions>
|
||||
<VersionOverrides xmlns="http://schemas.microsoft.com/office/taskpaneappversionoverrides" xsi:type="VersionOverridesV1_0">
|
||||
<Hosts>
|
||||
<Host xsi:type="Document">
|
||||
<DesktopFormFactor>
|
||||
<!-- You can add GetStarted information here if needed -->
|
||||
<FunctionFile resid="Commands.Url"/>
|
||||
<ExtensionPoint xsi:type="PrimaryCommandSurface">
|
||||
<OfficeTab id="TabHome">
|
||||
<Group id="AllTalkGroup">
|
||||
<Label resid="AllTalkGroup.Label"/>
|
||||
<Icon>
|
||||
<bt:Image size="16" resid="Icon.16x16"/>
|
||||
<bt:Image size="32" resid="Icon.32x32"/>
|
||||
<bt:Image size="80" resid="Icon.80x80"/>
|
||||
</Icon>
|
||||
<Control xsi:type="Button" id="AllTalkTaskpaneButton">
|
||||
<Label resid="AllTalkTaskpaneButton.Label"/>
|
||||
<Supertip>
|
||||
<Title resid="AllTalkTaskpaneButton.Label"/>
|
||||
<Description resid="AllTalkTaskpaneButton.Tooltip"/>
|
||||
</Supertip>
|
||||
<Icon>
|
||||
<bt:Image size="16" resid="Icon.16x16"/>
|
||||
<bt:Image size="32" resid="Icon.32x32"/>
|
||||
<bt:Image size="80" resid="Icon.80x80"/>
|
||||
</Icon>
|
||||
<Action xsi:type="ShowTaskpane">
|
||||
<TaskpaneId>ButtonId1</TaskpaneId>
|
||||
<SourceLocation resid="Taskpane.Url"/>
|
||||
</Action>
|
||||
</Control>
|
||||
</Group>
|
||||
</OfficeTab>
|
||||
</ExtensionPoint>
|
||||
</DesktopFormFactor>
|
||||
</Host>
|
||||
</Hosts>
|
||||
<Resources>
|
||||
<bt:Images>
|
||||
<bt:Image id="Icon.16x16" DefaultValue="http://127.0.0.1:7851/api/word_addin/assets/icon-16.png"/>
|
||||
<bt:Image id="Icon.32x32" DefaultValue="http://127.0.0.1:7851/api/word_addin/assets/icon-32.png"/>
|
||||
<bt:Image id="Icon.80x80" DefaultValue="http://127.0.0.1:7851/api/word_addin/assets/icon-80.png"/>
|
||||
</bt:Images>
|
||||
<bt:Urls>
|
||||
<!-- Ensure that these URLs are pointing to valid locations -->
|
||||
<bt:Url id="Commands.Url" DefaultValue="http://127.0.0.1:7851/api/word_addin/commands.html"/>
|
||||
<bt:Url id="Taskpane.Url" DefaultValue="http://127.0.0.1:7851/api/word_addin/taskpane.html"/>
|
||||
</bt:Urls>
|
||||
<bt:ShortStrings>
|
||||
<bt:String id="AllTalkGroup.Label" DefaultValue="AllTalk Controls"/>
|
||||
<bt:String id="AllTalkTaskpaneButton.Label" DefaultValue="Open AllTalk"/>
|
||||
</bt:ShortStrings>
|
||||
<bt:LongStrings>
|
||||
<bt:String id="AllTalkTaskpaneButton.Tooltip" DefaultValue="Open the AllTalk task pane to start using the add-in."/>
|
||||
</bt:LongStrings>
|
||||
</Resources>
|
||||
</VersionOverrides>
|
||||
</OfficeApp>
|
||||
@@ -0,0 +1,2 @@
|
||||
!function(){var t={35666:function(t){var r=function(t){"use strict";var r,e=Object.prototype,n=e.hasOwnProperty,i=Object.defineProperty||function(t,r,e){t[r]=e.value},o="function"==typeof Symbol?Symbol:{},u=o.iterator||"@@iterator",a=o.asyncIterator||"@@asyncIterator",c=o.toStringTag||"@@toStringTag";function s(t,r,e){return Object.defineProperty(t,r,{value:e,enumerable:!0,configurable:!0,writable:!0}),t[r]}try{s({},"")}catch(t){s=function(t,r,e){return t[r]=e}}function f(t,r,e,n){var o=r&&r.prototype instanceof y?r:y,u=Object.create(o.prototype),a=new j(n||[]);return i(u,"_invoke",{value:R(t,e,a)}),u}function l(t,r,e){try{return{type:"normal",arg:t.call(r,e)}}catch(t){return{type:"throw",arg:t}}}t.wrap=f;var h="suspendedStart",p="suspendedYield",v="executing",g="completed",d={};function y(){}function m(){}function b(){}var x={};s(x,u,(function(){return this}));var w=Object.getPrototypeOf,E=w&&w(w(P([])));E&&E!==e&&n.call(E,u)&&(x=E);var S=b.prototype=y.prototype=Object.create(x);function A(t){["next","throw","return"].forEach((function(r){s(t,r,(function(t){return this._invoke(r,t)}))}))}function O(t,r){function e(i,o,u,a){var c=l(t[i],t,o);if("throw"!==c.type){var s=c.arg,f=s.value;return f&&"object"==typeof f&&n.call(f,"__await")?r.resolve(f.__await).then((function(t){e("next",t,u,a)}),(function(t){e("throw",t,u,a)})):r.resolve(f).then((function(t){s.value=t,u(s)}),(function(t){return e("throw",t,u,a)}))}a(c.arg)}var o;i(this,"_invoke",{value:function(t,n){function i(){return new r((function(r,i){e(t,n,r,i)}))}return o=o?o.then(i,i):i()}})}function R(t,r,e){var n=h;return function(i,o){if(n===v)throw new Error("Generator is already running");if(n===g){if("throw"===i)throw o;return k()}for(e.method=i,e.arg=o;;){var u=e.delegate;if(u){var a=T(u,e);if(a){if(a===d)continue;return a}}if("next"===e.method)e.sent=e._sent=e.arg;else if("throw"===e.method){if(n===h)throw n=g,e.arg;e.dispatchException(e.arg)}else"return"===e.method&&e.abrupt("return",e.arg);n=v;var c=l(t,r,e);if("normal"===c.type){if(n=e.done?g:p,c.arg===d)continue;return{value:c.arg,done:e.done}}"throw"===c.type&&(n=g,e.method="throw",e.arg=c.arg)}}}function T(t,e){var n=e.method,i=t.iterator[n];if(i===r)return e.delegate=null,"throw"===n&&t.iterator.return&&(e.method="return",e.arg=r,T(t,e),"throw"===e.method)||"return"!==n&&(e.method="throw",e.arg=new TypeError("The iterator does not provide a '"+n+"' method")),d;var o=l(i,t.iterator,e.arg);if("throw"===o.type)return e.method="throw",e.arg=o.arg,e.delegate=null,d;var u=o.arg;return u?u.done?(e[t.resultName]=u.value,e.next=t.nextLoc,"return"!==e.method&&(e.method="next",e.arg=r),e.delegate=null,d):u:(e.method="throw",e.arg=new TypeError("iterator result is not an object"),e.delegate=null,d)}function I(t){var r={tryLoc:t[0]};1 in t&&(r.catchLoc=t[1]),2 in t&&(r.finallyLoc=t[2],r.afterLoc=t[3]),this.tryEntries.push(r)}function M(t){var r=t.completion||{};r.type="normal",delete r.arg,t.completion=r}function j(t){this.tryEntries=[{tryLoc:"root"}],t.forEach(I,this),this.reset(!0)}function P(t){if(t){var e=t[u];if(e)return e.call(t);if("function"==typeof t.next)return t;if(!isNaN(t.length)){var i=-1,o=function e(){for(;++i<t.length;)if(n.call(t,i))return e.value=t[i],e.done=!1,e;return e.value=r,e.done=!0,e};return o.next=o}}return{next:k}}function k(){return{value:r,done:!0}}return m.prototype=b,i(S,"constructor",{value:b,configurable:!0}),i(b,"constructor",{value:m,configurable:!0}),m.displayName=s(b,c,"GeneratorFunction"),t.isGeneratorFunction=function(t){var r="function"==typeof t&&t.constructor;return!!r&&(r===m||"GeneratorFunction"===(r.displayName||r.name))},t.mark=function(t){return Object.setPrototypeOf?Object.setPrototypeOf(t,b):(t.__proto__=b,s(t,c,"GeneratorFunction")),t.prototype=Object.create(S),t},t.awrap=function(t){return{__await:t}},A(O.prototype),s(O.prototype,a,(function(){return this})),t.AsyncIterator=O,t.async=function(r,e,n,i,o){void 0===o&&(o=Promise);var u=new O(f(r,e,n,i),o);return t.isGeneratorFunction(e)?u:u.next().then((function(t){return t.done?t.value:u.next()}))},A(S),s(S,c,"Generator"),s(S,u,(function(){return this})),s(S,"toString",(function(){return"[object Generator]"})),t.keys=function(t){var r=Object(t),e=[];for(var n in r)e.push(n);return e.reverse(),function t(){for(;e.length;){var n=e.pop();if(n in r)return t.value=n,t.done=!1,t}return t.done=!0,t}},t.values=P,j.prototype={constructor:j,reset:function(t){if(this.prev=0,this.next=0,this.sent=this._sent=r,this.done=!1,this.delegate=null,this.method="next",this.arg=r,this.tryEntries.forEach(M),!t)for(var e in this)"t"===e.charAt(0)&&n.call(this,e)&&!isNaN(+e.slice(1))&&(this[e]=r)},stop:function(){this.done=!0;var t=this.tryEntries[0].completion;if("throw"===t.type)throw t.arg;return this.rval},dispatchException:function(t){if(this.done)throw t;var e=this;function i(n,i){return a.type="throw",a.arg=t,e.next=n,i&&(e.method="next",e.arg=r),!!i}for(var o=this.tryEntries.length-1;o>=0;--o){var u=this.tryEntries[o],aLine truncated
|
||||
//# sourceMappingURL=polyfill.js.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"polyfill.js","mappings":"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 truncated
|
||||
@@ -0,0 +1,106 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=Edge" />
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<title>AllTalk TTS Add-in</title>
|
||||
<script src="https://appsforoffice.microsoft.com/lib/1.1/hosted/office.js"></script>
|
||||
<link rel="stylesheet"
|
||||
href="https://static2.sharepointonline.com/files/fabric/office-ui-fabric-core/11.0.0/css/fabric.min.css" />
|
||||
<link href="1fda685b81e1123773f6.css" rel="stylesheet" />
|
||||
<style>
|
||||
label {
|
||||
font-weight: 700;
|
||||
display: block;
|
||||
margin-top: 10px
|
||||
}
|
||||
|
||||
select {
|
||||
width: 100%;
|
||||
padding: 5px
|
||||
}
|
||||
|
||||
.nice-button {
|
||||
background-color: #0078d4;
|
||||
color: #fff;
|
||||
padding: 10px 20px;
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
font-size: 16px;
|
||||
transition: background-color .3s ease
|
||||
}
|
||||
|
||||
.nice-button:hover {
|
||||
background-color: #005a9e
|
||||
}
|
||||
|
||||
#audioSource {
|
||||
width: 300px;
|
||||
height: 50px
|
||||
}
|
||||
|
||||
.input-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-right: 10px
|
||||
}
|
||||
|
||||
.input-group {
|
||||
display: flex;
|
||||
justify-content: start;
|
||||
align-items: flex-end
|
||||
}
|
||||
|
||||
.input-group>.input-container {
|
||||
flex: 1
|
||||
}
|
||||
|
||||
input {
|
||||
width: 100%
|
||||
}
|
||||
</style>
|
||||
<script defer="defer" src="polyfill.js"></script>
|
||||
<script defer="defer" src="taskpane.js"></script>
|
||||
</head>
|
||||
|
||||
<body class="ms-font-m ms-welcome ms-Fabric">
|
||||
<header class="ms-welcome__header ms-bgColor-neutralLighter"><img width="90" height="90"
|
||||
src="http://127.0.0.1:7851/api/word_addin/assets/logo-filled.png" alt="AllTalk TTS" title="AllTalk TTS" />
|
||||
<h1 class="ms-font-su">AllTalk TTS</h1>
|
||||
</header>
|
||||
<main class="ms-welcome__main"><textarea id="text" rows="4" placeholder="Enter text here"
|
||||
style="display:none"></textarea> <label for="voice">Voice:</label> <select id="voice" name="voice"
|
||||
required></select> <label for="language">Language:</label> <select id="language" name="language"
|
||||
value="English" required>
|
||||
<option value="en" selected="selected">English</option>
|
||||
<option value="ar">Arabic</option>
|
||||
<option value="zh-cn">Chinese</option>
|
||||
<option value="cs">Czech</option>
|
||||
<option value="nl">Dutch</option>
|
||||
<option value="fr">French</option>
|
||||
<option value="de">German</option>
|
||||
<option value="hu">Hungarian</option>
|
||||
<option value="it">Italian</option>
|
||||
<option value="ja">Japanese</option>
|
||||
<option value="ko">Korean</option>
|
||||
<option value="pl">Polish</option>
|
||||
<option value="pt">Portuguese</option>
|
||||
<option value="ru">Russian</option>
|
||||
<option value="es">Spanish</option>
|
||||
<option value="tr">Turkish</option>
|
||||
</select><br><audio id="audioSource" controls autoplay></audio><br><button id="sendTextButton"
|
||||
class="nice-button">Send Text to TTS</button><br><br><br><br>
|
||||
<div class="input-group">
|
||||
<div class="input-container"><label for="serverIP">Server IP:</label> <input id="serverIP" name="serverIP"
|
||||
value="127.0.0.1" required></div>
|
||||
<div class="input-container"><label for="portNumber">Port Number:</label> <input type="number"
|
||||
id="portNumber" name="portNumber" value="7851" required></div>
|
||||
</div>
|
||||
</main>
|
||||
<script src="1995fcd6d39cade7d871.js"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,3 @@
|
||||
/*! For license information please see taskpane.js.LICENSE.txt */
|
||||
!function(){var t={27091:function(t){"use strict";t.exports=function(t,e){return e||(e={}),t?(t=String(t.__esModule?t.default:t),e.hash&&(t+=e.hash),e.maybeNeedQuotes&&/[\t\n\f\r "'=<>`]/.test(t)?'"'.concat(t,'"'):t):t}},44944:function(t,e,r){"use strict";t.exports=r.p+"assets/logo-filled.png"},36076:function(t,e,r){"use strict";t.exports=r.p+"1995fcd6d39cade7d871.js"},60806:function(t,e,r){"use strict";t.exports=r.p+"1fda685b81e1123773f6.css"}},e={};function r(n){var o=e[n];if(void 0!==o)return o.exports;var i=e[n]={exports:{}};return t[n](i,i.exports,r),i.exports}r.m=t,r.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return r.d(e,{a:e}),e},r.d=function(t,e){for(var n in e)r.o(e,n)&&!r.o(t,n)&&Object.defineProperty(t,n,{enumerable:!0,get:e[n]})},r.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(t){if("object"==typeof window)return window}}(),r.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},function(){var t;r.g.importScripts&&(t=r.g.location+"");var e=r.g.document;if(!t&&e&&(e.currentScript&&(t=e.currentScript.src),!t)){var n=e.getElementsByTagName("script");if(n.length)for(var o=n.length-1;o>-1&&!t;)t=n[o--].src}if(!t)throw new Error("Automatic publicPath is not supported in this browser");t=t.replace(/#.*$/,"").replace(/\?.*$/,"").replace(/\/[^\/]+$/,"/"),r.p=t}(),r.b=document.baseURI||self.location.href,function(){function t(e){return t="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},t(e)}function e(){"use strict";e=function(){return n};var r,n={},o=Object.prototype,i=o.hasOwnProperty,c=Object.defineProperty||function(t,e,r){t[e]=r.value},a="function"==typeof Symbol?Symbol:{},u=a.iterator||"@@iterator",f=a.asyncIterator||"@@asyncIterator",s=a.toStringTag||"@@toStringTag";function l(t,e,r){return Object.defineProperty(t,e,{value:r,enumerable:!0,configurable:!0,writable:!0}),t[e]}try{l({},"")}catch(r){l=function(t,e,r){return t[e]=r}}function h(t,e,r,n){var o=e&&e.prototype instanceof w?e:w,i=Object.create(o.prototype),a=new k(n||[]);return c(i,"_invoke",{value:I(t,r,a)}),i}function p(t,e,r){try{return{type:"normal",arg:t.call(e,r)}}catch(t){return{type:"throw",arg:t}}}n.wrap=h;var y="suspendedStart",v="suspendedYield",d="executing",m="completed",g={};function w(){}function b(){}function x(){}var E={};l(E,u,(function(){return this}));var L=Object.getPrototypeOf,_=L&&L(L(T([])));_&&_!==o&&i.call(_,u)&&(E=_);var j=x.prototype=w.prototype=Object.create(E);function O(t){["next","throw","return"].forEach((function(e){l(t,e,(function(t){return this._invoke(e,t)}))}))}function S(e,r){function n(o,c,a,u){var f=p(e[o],e,c);if("throw"!==f.type){var s=f.arg,l=s.value;return l&&"object"==t(l)&&i.call(l,"__await")?r.resolve(l.__await).then((function(t){n("next",t,a,u)}),(function(t){n("throw",t,a,u)})):r.resolve(l).then((function(t){s.value=t,a(s)}),(function(t){return n("throw",t,a,u)}))}u(f.arg)}var o;c(this,"_invoke",{value:function(t,e){function i(){return new r((function(r,o){n(t,e,r,o)}))}return o=o?o.then(i,i):i()}})}function I(t,e,n){var o=y;return function(i,c){if(o===d)throw new Error("Generator is already running");if(o===m){if("throw"===i)throw c;return{value:r,done:!0}}for(n.method=i,n.arg=c;;){var a=n.delegate;if(a){var u=P(a,n);if(u){if(u===g)continue;return u}}if("next"===n.method)n.sent=n._sent=n.arg;else if("throw"===n.method){if(o===y)throw o=m,n.arg;n.dispatchException(n.arg)}else"return"===n.method&&n.abrupt("return",n.arg);o=d;var f=p(t,e,n);if("normal"===f.type){if(o=n.done?m:v,f.arg===g)continue;return{value:f.arg,done:n.done}}"throw"===f.type&&(o=m,n.method="throw",n.arg=f.arg)}}}function P(t,e){var n=e.method,o=t.iterator[n];if(o===r)return e.delegate=null,"throw"===n&&t.iterator.return&&(e.method="return",e.arg=r,P(t,e),"throw"===e.method)||"return"!==n&&(e.method="throw",e.arg=new TypeError("The iterator does not provide a '"+n+"' method")),g;var i=p(o,t.iterator,e.arg);if("throw"===i.type)return e.method="throw",e.arg=i.arg,e.delegate=null,g;var c=i.arg;return c?c.done?(e[t.resultName]=c.value,e.next=t.nextLoc,"return"!==e.method&&(e.method="next",e.arg=r),e.delegate=null,g):c:(e.method="throw",e.arg=new TypeError("iterator result is not an object"),e.delegate=null,g)}function B(t){var e={tryLoc:t[0]};1 in t&&(e.catchLoc=t[1]),2 in t&&(e.finallyLoc=t[2],e.afterLoc=t[3]),this.tryEntries.push(e)}function N(t){var e=t.completion||{};e.type="normal",delete e.arg,t.completion=e}function k(t){this.tryEntries=[{tryLoc:"root"}],t.forEach(B,this),this.reset(!0)}function T(e){if(e||""===e){var n=e[u];if(n)return n.call(e);if("function"==typeof e.next)return e;if(!isNaN(e.length)){var o=-1,c=function t(){for(;++o<e.length;)if(i.call(e,o))return t.value=e[o],t.done=!1,t;return t.value=r,t.done=!0,t};return c.next=c}}throw new TLine truncated
|
||||
//# sourceMappingURL=taskpane.js.map
|
||||
@@ -0,0 +1 @@
|
||||
/*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"taskpane.js","mappings":"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 truncated
|
||||
|
Before Width: | Height: | Size: 476 KiB |
|
Before Width: | Height: | Size: 547 KiB |
|
Before Width: | Height: | Size: 156 KiB |