Compare commits
1245 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
d9d890975a | ||
|
8043fce1ce | ||
|
3677f6e268 | ||
|
0318700981 | ||
|
66cbbeed1a | ||
|
b262d28c10 | ||
|
38a9164e5c | ||
|
e472934bb4 | ||
|
6129780229 | ||
|
e821960c59 | ||
|
fa77d69bed | ||
|
7ab6a63a67 | ||
|
763a6a0763 | ||
|
dfbc95bd61 | ||
|
33387bd351 | ||
|
b02c4f48c3 | ||
|
006b9d575c | ||
|
4ebcd670e7 | ||
|
0b5daf162b | ||
|
11b5deecb8 | ||
|
fd849db239 | ||
|
6d9e735883 | ||
|
b5d3e5f066 | ||
|
a75f87e433 | ||
|
285615d67c | ||
|
eef8395205 | ||
|
465ab1ff23 | ||
|
1f51581ae3 | ||
|
87b547e724 | ||
|
3b83221cec | ||
|
f79855f8b2 | ||
|
1952c76533 | ||
|
92f0b1aaf5 | ||
|
ebea9d2692 | ||
|
a91ef76b64 | ||
|
0cd7f69931 | ||
|
b350812083 | ||
|
80ccc0b1d7 | ||
|
cc60c7adfb | ||
|
d61f6b8e99 | ||
|
7adc1f1cf5 | ||
|
7e177ee84c | ||
|
51046638d6 | ||
|
2522d44f13 | ||
|
018cab3ded | ||
|
a1714878a7 | ||
|
23b69ba121 | ||
|
9f6903e4e9 | ||
|
4c59ab5431 | ||
|
33d74e8e73 | ||
|
5f1ca7af51 | ||
|
56a5094881 | ||
|
cde810a9d0 | ||
|
73bb47f745 | ||
|
349d268189 | ||
|
3a8cbb07de | ||
|
800285f2cd | ||
|
d3add2561d | ||
|
621ad25a8a | ||
|
8dd8d7127d | ||
|
ce9b599501 | ||
|
28fc541891 | ||
|
cf2b693334 | ||
|
11672e9653 | ||
|
a42051bb40 | ||
|
aa620e1cf0 | ||
|
22bd9e3d7c | ||
|
6e774a1458 | ||
|
0e2078a268 | ||
|
51233e0cbe | ||
|
2ac5ec9feb | ||
|
bc6e8a9c08 | ||
|
39e0d0cfd6 | ||
|
a1a3def686 | ||
|
67804cad3c | ||
|
ce8f843746 | ||
|
0b954131b4 | ||
|
927bba6467 | ||
|
8f230e5c45 | ||
|
41238258ba | ||
|
1cf9be54c7 | ||
|
303a15fef3 | ||
|
04f93b193f | ||
|
fbf69cda19 | ||
|
8e42927880 | ||
|
4e254e42f7 | ||
|
cc72b93198 | ||
|
cc4783b85c | ||
|
5fd31999e7 | ||
|
9f9e7016e2 | ||
|
b96ba86be3 | ||
|
98ee26e353 | ||
|
e8244d61b7 | ||
|
87d2382828 | ||
|
03caf942b2 | ||
|
b215f3ba84 | ||
|
0f0225cfcd | ||
|
afb13bf976 | ||
|
06b8cf78d1 | ||
|
c2b979a05f | ||
|
4a967c0b80 | ||
|
ceb7d88cd9 | ||
|
17597fdaab | ||
|
702d468d2f | ||
|
f3d19fe95f | ||
|
69e81c4587 | ||
|
6ab743a2e2 | ||
|
b24c781a72 | ||
|
be3eb4033d | ||
|
0e7c0daebc | ||
|
3aa86f1e5a | ||
|
08b3f25f0b | ||
|
ecf1976837 | ||
|
6fd61b9591 | ||
|
a216d4bc9d | ||
|
935d817f6f | ||
|
b895bdec4f | ||
|
a5c665c275 | ||
|
82de23bb1a | ||
|
ab837561d9 | ||
|
14c73a71d2 | ||
|
3e39b99ed7 | ||
|
df49eac1da | ||
|
b8640f1f5a | ||
|
db9e02cf09 | ||
|
f529331698 | ||
|
3186e4322b | ||
|
6bda815669 | ||
|
c2b031efa5 | ||
|
d44119f9bf | ||
|
079043ff6a | ||
|
b6e743f032 | ||
|
818f2470e3 | ||
|
f36138d64e | ||
|
1da0717a45 | ||
|
f15289ad98 | ||
|
958b03bd5a | ||
|
218872ba75 | ||
|
53ea4cef57 | ||
|
85dfaff25f | ||
|
dadab1ad13 | ||
|
1e68e01e39 | ||
|
da9e6aaf6b | ||
|
a35551906a | ||
|
ca1cf9ed21 | ||
|
b69496c0f3 | ||
|
d03132d2ab | ||
|
3512bbb1eb | ||
|
e563094714 | ||
|
b32754134f | ||
|
0bf927a43f | ||
|
f6a3e98765 | ||
|
4f7969176f | ||
|
6272936e14 | ||
|
2c8597d742 | ||
|
56e26d438e | ||
|
e62a140698 | ||
|
ee827731b6 | ||
|
5de0630bb4 | ||
|
6d20b3dad2 | ||
|
b624999636 | ||
|
4f534a2c44 | ||
|
eb30f9a4e1 | ||
|
497c7c0678 | ||
|
a3160c12af | ||
|
59c80ca856 | ||
|
23be190e21 | ||
|
f86bee6768 | ||
|
65cde67b49 | ||
|
5c84c4cb91 | ||
|
6094be47f2 | ||
|
ba96930432 | ||
|
c0db39990d | ||
|
acc0130e7c | ||
|
35e1fc38cd | ||
|
9b39111f46 | ||
|
70ba5d9f24 | ||
|
782d003a91 | ||
|
c834d181a6 | ||
|
16873a9175 | ||
|
a13747b64f | ||
|
2b9a497eb0 | ||
|
22b0f83992 | ||
|
ae52548113 | ||
|
bfd7f5cef7 | ||
|
8d3a0f8c73 | ||
|
889874ecaf | ||
|
cfe2e6afd1 | ||
|
265705f087 | ||
|
b4b1001b70 | ||
|
92ab1a627c | ||
|
e3fafd5775 | ||
|
5061113bdd | ||
|
166b8adb62 | ||
|
abcfb93964 | ||
|
d5d6bd8910 | ||
|
3ef54e979b | ||
|
acc44fb83f | ||
|
d5e914634d | ||
|
25cba16e5f | ||
|
1de21cde0c | ||
|
0878f8f2f4 | ||
|
61b725a853 | ||
|
ee6ba8ee90 | ||
|
7febd37198 | ||
|
654de69533 | ||
|
051c59955b | ||
|
66ebd8554a | ||
|
4071115f7a | ||
|
f39a0831c5 | ||
|
eb8cd25409 | ||
|
074ac43acd | ||
|
8e56ecfcec | ||
|
71860e7b45 | ||
|
a4d41a6a07 | ||
|
d60b492730 | ||
|
f191d1e029 | ||
|
8d877b914a | ||
|
f7e3377d95 | ||
|
dab44c804f | ||
|
38fb8aa32f | ||
|
3b5844ba10 | ||
|
0f2698fb6c | ||
|
320ba88720 | ||
|
30cbc75304 | ||
|
f0f3dad6c4 | ||
|
f750f17ceb | ||
|
f64ce2b7b8 | ||
|
49ab9e80cb | ||
|
ff22dd4b7c | ||
|
e3bca2c49b | ||
|
7df36f5a72 | ||
|
a2501c245f | ||
|
8838ce757c | ||
|
3fbc3f67d2 | ||
|
a8f4a71327 | ||
|
dd85f99545 | ||
|
cd857f4daa | ||
|
6df24ad762 | ||
|
ba1823cad5 | ||
|
26741a5ccc | ||
|
afa1d60ed4 | ||
|
9784766ca2 | ||
|
3a954f3dea | ||
|
c594f279ae | ||
|
ce6429bf3a | ||
|
749e9540e3 | ||
|
5e82d3153a | ||
|
7ea35044d0 | ||
|
6f8710fd50 | ||
|
8e822c16e3 | ||
|
80a5ba91b8 | ||
|
93480636a3 | ||
|
83543c20bc | ||
|
eac95a1a5c | ||
|
9e8ba81379 | ||
|
219e10e4c9 | ||
|
e736bcbbda | ||
|
48d673227c | ||
|
c4a6d0456a | ||
|
1544c15627 | ||
|
82caea452a | ||
|
6a32c05c7e | ||
|
7b0472bb64 | ||
|
ea5cc27b2e | ||
|
f40056bed3 | ||
|
3ea542a01c | ||
|
0ecea3d2c4 | ||
|
35dc987657 | ||
|
c3d0cddecf | ||
|
66c4d8f076 | ||
|
d9c659de0e | ||
|
4fe21c7f34 | ||
|
71e91be293 | ||
|
43920fda4c | ||
|
fa6944ce9e | ||
|
8312189942 | ||
|
9c89b53626 | ||
|
78af3b7fff | ||
|
8974bf78d2 | ||
|
e8e339bd7e | ||
|
786c88cd06 | ||
|
db3b079a97 | ||
|
9fe14f94e2 | ||
|
46ff05b04f | ||
|
4a98b80cbf | ||
|
c4e73cee95 | ||
|
7d28bb575c | ||
|
a9dcefc772 | ||
|
26fdca22ae | ||
|
183b109844 | ||
|
b96a996071 | ||
|
1132ba1ac0 | ||
|
af49a25a9c | ||
|
6ceb514b19 | ||
|
3223b1ab27 | ||
|
addd60a2f8 | ||
|
11219c11f6 | ||
|
6aa06851d3 | ||
|
19e664cc8d | ||
|
638619b3b4 | ||
|
50f963ff6b | ||
|
5b43daa705 | ||
|
fbb88ab1f3 | ||
|
dc523737e8 | ||
|
e382052366 | ||
|
b66f793bc9 | ||
|
04902c4dcb | ||
|
b5d413fcda | ||
|
8b27cba4ba | ||
|
f65d9dc439 | ||
|
e33958cfda | ||
|
932037a841 | ||
|
3333c4d127 | ||
|
e741ce9906 | ||
|
14ed0a8db6 | ||
|
c53ea6d50b | ||
|
d1f9a2d5bc | ||
|
df2406bae8 | ||
|
23efe5fd11 | ||
|
592235f312 | ||
|
a4b7bfe479 | ||
|
cc0917dab3 | ||
|
ccdc98f9c2 | ||
|
56944ad594 | ||
|
1ba260e9b8 | ||
|
9a3e730ec5 | ||
|
fa0c0cbceb | ||
|
ff21c8130e | ||
|
38d7ec8c4f | ||
|
3e78db4318 | ||
|
e18138b5d6 | ||
|
6d4c138821 | ||
|
db97441380 | ||
|
c08099a512 | ||
|
aef9d2c34b | ||
|
8b5eb32047 | ||
|
2777896bb0 | ||
|
55f9604ba1 | ||
|
7b82f021d8 | ||
|
7ac8a9497d | ||
|
5dc66d1156 | ||
|
1ef2fd543d | ||
|
c9e994c3b6 | ||
|
51906ba4f1 | ||
|
0e878edc1e | ||
|
2b08e47377 | ||
|
4b2d3bb334 | ||
|
b4555a6beb | ||
|
839755e82f | ||
|
4abbe0839e | ||
|
778268d898 | ||
|
fee9354ea6 | ||
|
f48ad3755e | ||
|
755511ed5c | ||
|
09f9c00b02 | ||
|
cdff7cc7f4 | ||
|
6720fc5f08 | ||
|
172e3f7a1d | ||
|
73203a13e3 | ||
|
b86e15a79f | ||
|
cacd127c76 | ||
|
2a10d19cd5 | ||
|
3d2f5ad0da | ||
|
074a0a4530 | ||
|
bf01337ce3 | ||
|
347963c0f5 | ||
|
bf742d86c1 | ||
|
4e13ec3d6b | ||
|
dd01e81e45 | ||
|
9de74281f6 | ||
|
f96b4c2414 | ||
|
d2a2826a82 | ||
|
2e84fa7407 | ||
|
3c54b6bd2b | ||
|
8cd41a62a8 | ||
|
98d104cbf2 | ||
|
7200896940 | ||
|
a8a392b20d | ||
|
7ab7dba5c8 | ||
|
f98d4a38e0 | ||
|
ff0a80362a | ||
|
11756788aa | ||
|
20e7a472be | ||
|
acab6644f7 | ||
|
ec4f62f54a | ||
|
5afe932126 | ||
|
857ce5b90d | ||
|
6394314d25 | ||
|
2ee83c7239 | ||
|
3b2fcc9805 | ||
|
c0448db0ec | ||
|
d3e49efd69 | ||
|
a0e890a438 | ||
|
cc5d3305fe | ||
|
a6b1f093e1 | ||
|
43a1583731 | ||
|
7e4eed04e6 | ||
|
ba9b5de461 | ||
|
72702ee70a | ||
|
1d54687577 | ||
|
257d99e355 | ||
|
87a10c8e11 | ||
|
0957fbc923 | ||
|
b559582dc4 | ||
|
371e1b8cac | ||
|
e8aeb1eaa7 | ||
|
b133364b77 | ||
|
e6a3ae241d | ||
|
022fda0aa6 | ||
|
37468e3cc9 | ||
|
b9429c7655 | ||
|
9eef8fcb11 | ||
|
33e156ef9a | ||
|
2c4503ade8 | ||
|
01291dc4e3 | ||
|
3ffacaed97 | ||
|
7d7702bb79 | ||
|
333e66786d | ||
|
485a747d55 | ||
|
8339e72ef5 | ||
|
8a2df2dbb4 | ||
|
02eadeeaa3 | ||
|
6a09338af5 | ||
|
a69c89255b | ||
|
a1db94c0af | ||
|
fbabfed566 | ||
|
5bf1202215 | ||
|
9c829ac91a | ||
|
ad013bf4d3 | ||
|
4c9e61bb35 | ||
|
852b3c021c | ||
|
ae3587a615 | ||
|
e897512ee1 | ||
|
f55f1f2938 | ||
|
065e23d5e3 | ||
|
728e7bcca1 | ||
|
514ae768b7 | ||
|
cda99da5b4 | ||
|
816798e8b5 | ||
|
01a916d2dd | ||
|
aca23038bb | ||
|
b1d361aaae | ||
|
6fb00c7d91 | ||
|
bde95029b3 | ||
|
130ae7e398 | ||
|
8ecc64d9a1 | ||
|
29c5bb0299 | ||
|
f27562f182 | ||
|
cb9043ffd4 | ||
|
dc9401ff0f | ||
|
9ca73928ef | ||
|
eba5da7970 | ||
|
caa8c99f14 | ||
|
d4f80eeaa8 | ||
|
66049c3c06 | ||
|
900525e584 | ||
|
0825f5eee0 | ||
|
0bd7bfafc5 | ||
|
89a06b65ec | ||
|
d5561c2212 | ||
|
099f82cc60 | ||
|
171360b757 | ||
|
81fe3cd6a0 | ||
|
1367bbb611 | ||
|
764e4e9c5d | ||
|
1449a71087 | ||
|
e07300fe70 | ||
|
6e18b42c51 | ||
|
3b1a984e23 | ||
|
adb8371089 | ||
|
fa07de80fb | ||
|
3742642128 | ||
|
f86910b089 | ||
|
8ae4990f74 | ||
|
1dc46df84b | ||
|
d0224a5e50 | ||
|
70956fafeb | ||
|
c34e9ccefb | ||
|
127e2db94f | ||
|
403026ea52 | ||
|
8c12dd0127 | ||
|
bad81448e2 | ||
|
07d26d3125 | ||
|
2f0289f1c7 | ||
|
2ffc38154b | ||
|
c48ac96104 | ||
|
cd3f272271 | ||
|
7b251339f1 | ||
|
5a5f7feefd | ||
|
02359b9f4f | ||
|
75668e1534 | ||
|
92cd384486 | ||
|
fd17bb59c8 | ||
|
790c688ace | ||
|
b051d08ae0 | ||
|
f3ba60f4e1 | ||
|
809019634d | ||
|
03f5697809 | ||
|
f0cdb45f32 | ||
|
b5e3f11beb | ||
|
7b50b9f0f3 | ||
|
2bce23af19 | ||
|
b4869256fe | ||
|
88519b3786 | ||
|
906c322b40 | ||
|
f5909710f0 | ||
|
db5de17604 | ||
|
443d857e7a | ||
|
2640c7aded | ||
|
34066aa4f6 | ||
|
1a2220bfe4 | ||
|
15fefdf5c4 | ||
|
7b6b402d9d | ||
|
b5dd079f04 | ||
|
f0bc01a338 | ||
|
d3c971e033 | ||
|
21b9a9fe24 | ||
|
7ee72e0231 | ||
|
62accf2d7b | ||
|
9b456c83bb | ||
|
ad9f910163 | ||
|
baeb771c29 | ||
|
d57362c3c3 | ||
|
21967880c4 | ||
|
73a96c654a | ||
|
4d67354ea6 | ||
|
767dfc520c | ||
|
daff5098f8 | ||
|
6b4fe5a349 | ||
|
4d4b6f2c08 | ||
|
c333eb188e | ||
|
50ac1adc45 | ||
|
fcf5488b01 | ||
|
f429e00010 | ||
|
719f4c4d83 | ||
|
59f558ef93 | ||
|
4b212bd442 | ||
|
776a6fd8b2 | ||
|
0201b2e44c | ||
|
4d31d2238d | ||
|
68b1c8953e | ||
|
d83590dc35 | ||
|
fa7894de50 | ||
|
e6b191abd2 | ||
|
06a5250f61 | ||
|
c7e72e52db | ||
|
b9c1ee4346 | ||
|
b6996a15fe | ||
|
b453e5fd85 | ||
|
c8dc2a2637 | ||
|
0936b02287 | ||
|
3bed1af628 | ||
|
dd7a343c65 | ||
|
df199516c2 | ||
|
dda7ab008b | ||
|
73f564cfa8 | ||
|
03a4e8f3be | ||
|
9c56579df1 | ||
|
56ee649196 | ||
|
3729b44f37 | ||
|
db322756f6 | ||
|
9dd2808509 | ||
|
4a8851aff1 | ||
|
bd3d3375c3 | ||
|
d192e21093 | ||
|
0036a779cf | ||
|
435699d387 | ||
|
24b55116f2 | ||
|
b84ae93511 | ||
|
4f427d5700 | ||
|
d7f5828710 | ||
|
87de3dc10f | ||
|
99cf22041f | ||
|
4d55e19bd0 | ||
|
ca9bac0942 | ||
|
8a8386640d | ||
|
3c1d87751e | ||
|
40eccd653f | ||
|
d7e541ffa7 | ||
|
bdad75699e | ||
|
60ef9145b9 | ||
|
328ea46161 | ||
|
0571381253 | ||
|
e0214e54f8 | ||
|
52a954ebaa | ||
|
e6b58a8613 | ||
|
74d277714b | ||
|
c04dde82d2 | ||
|
631b9b3bf6 | ||
|
e5d5df17db | ||
|
9f52168d59 | ||
|
adfdd3de9a | ||
|
012b6a76a9 | ||
|
c273a40f44 | ||
|
8c21d4e5ff | ||
|
bc5fd76cc2 | ||
|
16598b3034 | ||
|
4017e6c62c | ||
|
8d49db9d69 | ||
|
480735bb8d | ||
|
3bfd2cb746 | ||
|
da52b7446d | ||
|
48f3081442 | ||
|
f531821050 | ||
|
8501cb3d54 | ||
|
54df4ec325 | ||
|
4793f2f495 | ||
|
599dfc9874 | ||
|
cf347d9854 | ||
|
cb9afff8f2 | ||
|
30d1d10f16 | ||
|
0f7aeb462a | ||
|
ed21f10663 | ||
|
e1e80397ce | ||
|
da6698eb96 | ||
|
b0baad1211 | ||
|
14259f1652 | ||
|
0aab867412 | ||
|
473f02951d | ||
|
d6731f4adf | ||
|
b3b8a347e1 | ||
|
66071835ac | ||
|
f2e2e87f18 | ||
|
3f4e68294a | ||
|
26a59857b3 | ||
|
dc7f9a0e15 | ||
|
6397784a2b | ||
|
9d6ae2fe2e | ||
|
28fa21a6b4 | ||
|
605e04f48f | ||
|
35230d3a59 | ||
|
38b614e88c | ||
|
cb0be0bf17 | ||
|
70b3e7a5f5 | ||
|
105c3a23d5 | ||
|
7b323207c5 | ||
|
3a556ebc5f | ||
|
2e96f8072a | ||
|
bfeef443f5 | ||
|
99f93f93a6 | ||
|
297cf319f1 | ||
|
6833ae4c3c | ||
|
6cf6c815e9 | ||
|
326d7641ea | ||
|
8685f9e5bf | ||
|
b53fd5c123 | ||
|
ac7c751439 | ||
|
6b9777f3a2 | ||
|
7cc9fb4fcf | ||
|
d702714c34 | ||
|
7e971e2cb7 | ||
|
9818f6ec42 | ||
|
c2efe5cba1 | ||
|
96458c2bba | ||
|
dcfc1d83cf | ||
|
d45467a3c4 | ||
|
f1683cb4a8 | ||
|
21f098e8ec | ||
|
00e163516b | ||
|
52f0e496ef | ||
|
2b452ead0b | ||
|
78ccc10a53 | ||
|
1cccd90546 | ||
|
04847306af | ||
|
4d6d5a27cb | ||
|
6224ec326e | ||
|
39cd234268 | ||
|
18481feb7e | ||
|
895fd786e9 | ||
|
ca989775dd | ||
|
3d8dc7a9bd | ||
|
7746f3168f | ||
|
20303d9dfc | ||
|
64258ab089 | ||
|
976eaa6333 | ||
|
18d0012c29 | ||
|
21ec512239 | ||
|
d98168ebbe | ||
|
3037c3d2f9 | ||
|
3233377abd | ||
|
55ea032a86 | ||
|
aa42c3f619 | ||
|
b5419d3789 | ||
|
ba650f9be2 | ||
|
dc0cb3ba9f | ||
|
451fc16693 | ||
|
1643628a69 | ||
|
efc6e6d321 | ||
|
606b10a1fa | ||
|
e4822120a7 | ||
|
4cf43889c3 | ||
|
1405a276a9 | ||
|
25bb1ee078 | ||
|
3e32ced744 | ||
|
d62a9fffd4 | ||
|
fef588b00b | ||
|
11255790c8 | ||
|
62cce76791 | ||
|
0204c76d69 | ||
|
0491d43afc | ||
|
5b01ca8c06 | ||
|
3bf1aacd05 | ||
|
e9c844b882 | ||
|
b10afc14b5 | ||
|
d52af3b466 | ||
|
6d419a5702 | ||
|
fa833b5b68 | ||
|
0379a0ea2e | ||
|
1f56a6140a | ||
|
71683c859b | ||
|
44593719f5 | ||
|
ffd2894d5e | ||
|
d86e02ce1e | ||
|
a1f1e492cb | ||
|
9918a60ff1 | ||
|
da98fd2478 | ||
|
5205bf77ad | ||
|
5ebd92bb4b | ||
|
6fecb5f908 | ||
|
ea3c5b5740 | ||
|
6ac69f3091 | ||
|
e6938250b6 | ||
|
61564c2edf | ||
|
92caf3d5fc | ||
|
a598823573 | ||
|
7b159f0f92 | ||
|
0826d1e14c | ||
|
28803c6b87 | ||
|
0b14afbb61 | ||
|
f592c8067c | ||
|
520fde1477 | ||
|
813b666c58 | ||
|
9ea33018cf | ||
|
46a5bf7f77 | ||
|
42d40a79bd | ||
|
42708e7295 | ||
|
3ea18048ec | ||
|
deea42a000 | ||
|
f9dcb5d7a6 | ||
|
75b575d81d | ||
|
5a72d0a8cd | ||
|
1d91356268 | ||
|
0723913a3b | ||
|
ff82ae986b | ||
|
426388872a | ||
|
751234e65b | ||
|
069ebc22da | ||
|
0bb660ab2f | ||
|
270ffb6459 | ||
|
19e70606c8 | ||
|
3e0772d955 | ||
|
380f24ca81 | ||
|
2c881479ed | ||
|
80b9acc712 | ||
|
af4cf4857e | ||
|
f4e409187e | ||
|
cfa6549a65 | ||
|
e570bf2e2a | ||
|
61a9a9e47a | ||
|
5f3dd62f81 | ||
|
f48319c350 | ||
|
15dae8f245 | ||
|
617551db49 | ||
|
e14e823fec | ||
|
a7a989407c | ||
|
ec75219f18 | ||
|
b12c042bd8 | ||
|
4e03b34f51 | ||
|
6f1b06a419 | ||
|
3726a926b7 | ||
|
50ff96b3c5 | ||
|
807e88b93b | ||
|
a17554cbcc | ||
|
6721d64291 | ||
|
babbc2e9c7 | ||
|
3a4e534091 | ||
|
f2ba7e3938 | ||
|
7f1cdb9ddc | ||
|
48846aad7f | ||
|
bfb2de9ea1 | ||
|
6a01467ac8 | ||
|
72fb482dc7 | ||
|
7c70999f33 | ||
|
7e8e31a8c0 | ||
|
4faee09aa1 | ||
|
c58c93856c | ||
|
373df31f6c | ||
|
e7b3a38402 | ||
|
17521975c1 | ||
|
cc4d7ebc9d | ||
|
093e01dd4e | ||
|
37eba531e9 | ||
|
b2d61d369a | ||
|
5bd6906c1e | ||
|
92a1fcc69e | ||
|
005880cd78 | ||
|
d27e31f07f | ||
|
f6e40e6061 | ||
|
7487585d65 | ||
|
29be0775ec | ||
|
d3bf39c322 | ||
|
7db3047999 | ||
|
28b996af76 | ||
|
90c9c764df | ||
|
1da21aa094 | ||
|
83623d1ab8 | ||
|
dd6a0bdb76 | ||
|
b7b107a73f | ||
|
569d8d2c0c | ||
|
50d1977d50 | ||
|
96d7141976 | ||
|
6fcbd07065 | ||
|
b3d7946592 | ||
|
4ac4a225a7 | ||
|
c96609640d | ||
|
bd3667117e | ||
|
234595eeeb | ||
|
37bb25682e | ||
|
443fe1e720 | ||
|
83083a68ac | ||
|
4fc57153e7 | ||
|
3ab5c9f3b8 | ||
|
8121c3a849 | ||
|
308fd190f3 | ||
|
55118815b4 | ||
|
a59631609c | ||
|
91a35fc688 | ||
|
1ad44bf98f | ||
|
7d261a14c2 | ||
|
8d80abddd2 | ||
|
d4802daaaa | ||
|
e4086e4fd2 | ||
|
dbbe11acbf | ||
|
0c84edf173 | ||
|
e5ad4b9504 | ||
|
d84e9a776b | ||
|
228068b667 | ||
|
cbc454ebf7 | ||
|
87e4ab0cb7 | ||
|
ca5eff8b35 | ||
|
87d9bf1800 | ||
|
777c2d6e1e | ||
|
86798b3896 | ||
|
cdceae9cf1 | ||
|
08d07c5997 | ||
|
5532bd4ad6 | ||
|
11a536b03f | ||
|
acfb7b601a | ||
|
d3823183d6 | ||
|
2fa33aad8d | ||
|
ef025efd30 | ||
|
eba6e6aeda | ||
|
0250541fd0 | ||
|
045e4bbd10 | ||
|
5cc45dcc2e | ||
|
8a17da84cf | ||
|
1fd3f04030 | ||
|
f8b589cc1d | ||
|
695152e138 | ||
|
f95b63ea5f | ||
|
47d69f19f3 | ||
|
d12c5b1941 | ||
|
60dbecef9a | ||
|
257e5f99a4 | ||
|
3de900fbdf | ||
|
e073eed95c | ||
|
2706810b4e | ||
|
c4e16b4955 | ||
|
04c009416a | ||
|
6c3e151c7b | ||
|
33f333c63c | ||
|
16dbcabdd9 | ||
|
652a8b1685 | ||
|
75ebbe890c | ||
|
8c1e48d97c | ||
|
2b8236a9b2 | ||
|
253697f5d6 | ||
|
8a650f4643 | ||
|
a68bd1d899 | ||
|
f65fedce15 | ||
|
5f41d8100d | ||
|
95586403c8 | ||
|
6f87ca7a39 | ||
|
3ad903fad6 | ||
|
513a85e6c7 | ||
|
3853bd6ccf | ||
|
a82a1ecd71 | ||
|
f4b93ac3e8 | ||
|
599fe42710 | ||
|
2ceea78fd1 | ||
|
79b545a0f1 | ||
|
ca665796ef | ||
|
04d3937818 | ||
|
975fea2458 | ||
|
c2757716ba | ||
|
7d96ab4264 | ||
|
a7e907370d | ||
|
0df0270d25 | ||
|
2d19b5ff65 | ||
|
e4ac5e74db | ||
|
390a39fa64 | ||
|
eb37febce8 | ||
|
84ca7974e9 | ||
|
e2f08a17d4 | ||
|
e1e1f94fa3 | ||
|
707096b48c | ||
|
d85bbae478 | ||
|
b3a95b2f7e | ||
|
bc09f90bd3 | ||
|
74a8674b63 | ||
|
e3385b8804 | ||
|
e342d53b76 | ||
|
f782ebb320 | ||
|
b41de02624 | ||
|
1c8d891a7d | ||
|
4171baa6de | ||
|
bb769cf6c2 | ||
|
42da74d557 | ||
|
8ddbb96500 | ||
|
ac573a6961 | ||
|
44ce9a5368 | ||
|
d9caa75a92 | ||
|
2c63803f83 | ||
|
58b3aaa5fe | ||
|
f1b700ea5d | ||
|
7324e4f1c8 | ||
|
0d3c97e9fe | ||
|
039c4b7006 | ||
|
fbe2cfad68 | ||
|
db8835ff2f | ||
|
9938c24b00 | ||
|
fc61dd8d7e | ||
|
da4253abbb | ||
|
0010c7d695 | ||
|
d811ebebd0 | ||
|
0afe5bc381 | ||
|
b9c3e84c79 | ||
|
90cf803913 | ||
|
f02489a86f | ||
|
b57ddc180c | ||
|
4cc02540ea | ||
|
bd6080c52e | ||
|
2ef04456a1 | ||
|
cb6a58550c | ||
|
adcc0a2d86 | ||
|
138d17719c | ||
|
dfe2f502c8 | ||
|
9afe6b79ec | ||
|
fb1be8b4c1 | ||
|
f9dc45870a | ||
|
00ee870d8c | ||
|
d69f7a405c | ||
|
0d06fcd16b | ||
|
e780af7fc2 | ||
|
4e0d2a24a3 | ||
|
5465f6e1c3 | ||
|
3fefc528ab | ||
|
36c6798f14 | ||
|
f1bd7db7c1 | ||
|
60bffb61a5 | ||
|
04b9bb1ac3 | ||
|
f68366c22a | ||
|
debfbf83d7 | ||
|
79abc3d667 | ||
|
771235be66 | ||
|
a9eafb4a60 | ||
|
26bab1bb6e | ||
|
cbe99e7914 | ||
|
7b092dd787 | ||
|
fc4ff2bd35 | ||
|
c07915283b | ||
|
070412d787 | ||
|
28782c051a | ||
|
eaa0c58243 | ||
|
cbd3c293f8 | ||
|
9512fd5ae2 | ||
|
689d3a4cdc | ||
|
1fd0422b43 | ||
|
c9aaf751f0 | ||
|
fe95cf02c0 | ||
|
8d3b4e1c7d | ||
|
98e14a9d4a | ||
|
4251e1ca7c | ||
|
d77739707a | ||
|
568e06ed2f | ||
|
604846b0c6 | ||
|
2adfb7c910 | ||
|
6d53d4ccf4 | ||
|
a1e05ffb62 | ||
|
7f40fcfd47 | ||
|
5ec945faac | ||
|
586d83c550 | ||
|
9718afaa0d | ||
|
0336e0f526 | ||
|
7019f31308 | ||
|
9cec875081 | ||
|
5d0db91f45 | ||
|
12a182e258 | ||
|
246eebbce6 | ||
|
7d03872acb | ||
|
2a25e75154 | ||
|
ac2af5c08f | ||
|
75406e49c7 | ||
|
4136b52108 | ||
|
d9479e2a0e | ||
|
4db43592f1 | ||
|
e10c832b46 | ||
|
f0fbf58258 | ||
|
4bbcbd66bc | ||
|
06770746d9 | ||
|
fa2365c95e | ||
|
035d64db6a | ||
|
200d6713b6 | ||
|
be771843b1 | ||
|
9e9a289d63 | ||
|
47ea4ffb36 | ||
|
15c83391b9 | ||
|
09c0ecff3e | ||
|
fab386af69 | ||
|
582e200d6a | ||
|
b413eeea85 | ||
|
61f485756d | ||
|
8a4e76795a | ||
|
807120201f | ||
|
3c1c785dfa | ||
|
f3374ba21a | ||
|
67a104af8b | ||
|
ffeb745f83 | ||
|
1143ad88fd | ||
|
0de24ca000 | ||
|
dcc782216f | ||
|
ae3b7e8f76 | ||
|
9f7533c037 | ||
|
a32cd29f51 | ||
|
a180dfa7e4 | ||
|
6bcdf53c97 | ||
|
8c7c6994b3 | ||
|
28b71a37e6 | ||
|
8903557df0 | ||
|
7b2b07a4bf | ||
|
ae132e0c0f | ||
|
fd2a8d7736 | ||
|
71937a6fd9 | ||
|
baa0537208 | ||
|
d004c9ebed | ||
|
40368d0466 | ||
|
a647abcef7 | ||
|
f7f7f96496 | ||
|
99dae6e553 | ||
|
98d115a799 | ||
|
dc0c69476f | ||
|
5517be5243 | ||
|
2b10c3e872 | ||
|
0b554f18f6 | ||
|
ad625ef393 | ||
|
9e96281f03 | ||
|
4885e3a7e1 | ||
|
8ab5d74abd | ||
|
7524fe4ad5 | ||
|
7aebcac434 | ||
|
4c7c00ccbc | ||
|
43eb4d5e83 | ||
|
a758dd1595 | ||
|
d1437ba71f | ||
|
29a25e4dcb | ||
|
087d0b5722 | ||
|
1dbd8b6679 | ||
|
29aa1fd368 | ||
|
a8ebece8d4 | ||
|
44fd993dbc | ||
|
45a3872dc6 | ||
|
46628277f1 | ||
|
03d481ab67 | ||
|
c089e6bc51 | ||
|
c85a16054f | ||
|
53fc89fb9a | ||
|
680c7fc71f | ||
|
89266ba006 | ||
|
ceb458e2ce | ||
|
3e5ed4dac1 | ||
|
5b2519d0e9 | ||
|
ca4ae3b417 | ||
|
4641a6d515 | ||
|
c5b9bc3a3f | ||
|
398921dd25 | ||
|
39fab4afc1 | ||
|
1f33cd547d | ||
|
76ddef5ee1 | ||
|
d5cc5c9e28 | ||
|
dd30c70f87 | ||
|
844c52d749 | ||
|
fe03db85fd | ||
|
8c27eade1c | ||
|
edc90e5bae | ||
|
e509693fc1 | ||
|
9c62da1a5d | ||
|
0fc36c91af | ||
|
d2e2f1fe4f | ||
|
4504f26fae | ||
|
9da9467f38 | ||
|
ef6fdd8d49 | ||
|
5818292046 | ||
|
7a2fd74d6c | ||
|
acc848fda4 | ||
|
ddcae23f20 | ||
|
ca4d454d1a | ||
|
01f64cc8ec | ||
|
085a256499 | ||
|
ef9f63b8df | ||
|
fe88ada373 | ||
|
4129aff8c1 | ||
|
3b0c792c5a | ||
|
15dc87c407 | ||
|
87f7429501 | ||
|
a5c7414fc3 | ||
|
d7cff0709f | ||
|
010eb395ef | ||
|
a49a1f4558 | ||
|
5ea82af9b3 | ||
|
85e51bd3a9 | ||
|
bdf11d9206 | ||
|
a6efaaa381 | ||
|
57ac020547 | ||
|
7fa6de855d | ||
|
cdb3234111 | ||
|
3ad682dba2 | ||
|
c14ea07dd5 | ||
|
bbb068be72 | ||
|
6f97320c0d | ||
|
f76fff5959 | ||
|
18a87d9d24 | ||
|
49291a1de2 | ||
|
b9741fe577 | ||
|
9a6b9851db | ||
|
07d3a968dd | ||
|
2001aa70d2 | ||
|
3328749f29 | ||
|
36087eeace | ||
|
72e7859174 | ||
|
fde356be4d | ||
|
bfe826001b | ||
|
3ba4d011de | ||
|
31cd9437ef | ||
|
622fa4a64e | ||
|
694b5a3590 | ||
|
dabbf51322 | ||
|
cf34cb6bee | ||
|
a24f6ff5ab | ||
|
7d81ecbbff | ||
|
daa4a9c637 | ||
|
7e0efb0c1c | ||
|
786be0878d | ||
|
93769ddcda | ||
|
ccd0176c1e | ||
|
5e971d4dc0 | ||
|
35ca5a7618 | ||
|
98db8862b5 | ||
|
34749d9d6a | ||
|
d62f4cc124 | ||
|
341b05dc2f | ||
|
7a1391ce08 | ||
|
42ce1b498d | ||
|
9a1a9245c8 | ||
|
b453868f97 | ||
|
1278094ccd | ||
|
1661a062db | ||
|
2cfc7b2887 | ||
|
eeb940480e | ||
|
0fa7a13aef | ||
|
1c4ce29d56 | ||
|
1edc79864a | ||
|
eb12f3db64 | ||
|
fccd631c00 | ||
|
bde893b665 | ||
|
de0be188ff | ||
|
11d6bd414c | ||
|
d0eef70109 | ||
|
a5d4b5dfe2 | ||
|
091b72e291 | ||
|
12e717d1b7 | ||
|
e1d2660a59 | ||
|
98ad3b4ff0 | ||
|
096ada6e3d | ||
|
6b78c57204 | ||
|
15686caf50 | ||
|
c6309b83f8 | ||
|
fc5c4aa2fb | ||
|
b97dc18654 | ||
|
be9695307a | ||
|
63d58b82b5 | ||
|
0776383e03 | ||
|
8e2603b91e | ||
|
de683de7a3 | ||
|
db101b788a | ||
|
eab6d2abea | ||
|
84e7ed0c91 | ||
|
b7b1e583ee | ||
|
bde3bc5933 | ||
|
335771fe77 | ||
|
eaf310c00b | ||
|
27c5d54cc5 | ||
|
47489571da | ||
|
25a673b66f | ||
|
f73178b9b0 | ||
|
852b4216ca | ||
|
9ff8dad6b8 | ||
|
99a9b854d3 | ||
|
ee0b957510 | ||
|
05b060a165 | ||
|
9d84046a77 | ||
|
83646c130b | ||
|
17ac07e263 | ||
|
b87f7983b3 | ||
|
59a56d5507 | ||
|
6be21bf8fc | ||
|
affc55cb24 | ||
|
305dac7e38 | ||
|
449f5a55d1 | ||
|
ea7690c2cd | ||
|
9f117ee88f | ||
|
122a6e3849 | ||
|
3ec1902045 | ||
|
954a26b0c6 | ||
|
d72784a0f8 | ||
|
067bd2a089 | ||
|
699f1c3ba0 | ||
|
f7c9eff10a | ||
|
391b61c073 | ||
|
4fb85cb4db | ||
|
46e7a64185 | ||
|
5b85d58b8b | ||
|
becbbb24b2 | ||
|
cd6edb14d3 | ||
|
080fa52059 | ||
|
161c25aea9 | ||
|
2f79283e28 | ||
|
21e7c9389f | ||
|
7fffa7b39f | ||
|
0e9824ae7e | ||
|
0cd07e8c05 | ||
|
fe4c7d745e | ||
|
43bef81d60 | ||
|
1c1b853941 | ||
|
6b7f3b0fb5 |
24
.github/FAQ.md
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
# Frequently Asked Questions
|
||||
Please read this FAQ before asking or making a bug report.
|
||||
|
||||
### General fixes:
|
||||
*Do all these steps so you can fix some issues.*
|
||||
- Restart the application
|
||||
- Go to your Windows %AppData% (Win + R, then put %appdata% and press Enter) and delete the "**voice-changer-native-client**" folder
|
||||
- Extract your .zip to a new location and avoid folders with space or specials characters (also avoid long file paths)
|
||||
- If you don't have a GPU or have a too old GPU, try using the [Colab Version](https://colab.research.google.com/github/w-okada/voice-changer/blob/master/Realtime_Voice_Changer_on_Colab.ipynb) instead
|
||||
|
||||
### 1. AMD GPU don't appear or not working
|
||||
> Please download the **latest DirectML version**, use the **f0 det. rmvpe_onnx** and .ONNX models only! (.pth models do not work properly, use the "Export to ONNX" it can take a while)
|
||||
|
||||
### 2. NVidia GPU don't appear or not working
|
||||
> Make sure that the [NVidia CUDA Toolkit](https://developer.nvidia.com/cuda-downloads) drivers are installed on your PC and up-to-date
|
||||
|
||||
### 3. High CPU usage
|
||||
> Decrease your EXTRA value and put the index feature to 0
|
||||
|
||||
### 4. High Latency
|
||||
> Decrease your chunk value until you find a good mix of quality and response time
|
||||
|
||||
### 5. I'm hearing my voice without changes
|
||||
> Make sure to disable **passthru** mode
|
22
.github/ISSUE_TEMPLATE/feature-request.yaml
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
name: Feature Request
|
||||
description: Do you have some feature request? Use this template
|
||||
title: "[REQUEST]: "
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: When creating a feature request, please be aware that **we do not guarantee that your idea will be implemented**. We are always working to make our software better, so please be pacient and do not put pressure on our devs.
|
||||
- type: input
|
||||
id: few-words
|
||||
attributes:
|
||||
label: In a few words, describe your idea
|
||||
description: With a few words, briefly describe your idea
|
||||
placeholder: ex. My idea is to implement rmvpe!
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: request
|
||||
attributes:
|
||||
label: More information
|
||||
description: If you have a complex idea, please use this field to describe it more, please provide enough information so we can understand and implement your idea
|
||||
validations:
|
||||
required: false
|
66
.github/ISSUE_TEMPLATE/issue.yaml
vendored
Normal file
@ -0,0 +1,66 @@
|
||||
name: Issue or Bug Report for v.1.x.x.x
|
||||
description: Please provide as much detail as possible to convey the history of your problem.
|
||||
title: "[ISSUE]: "
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: Please read our [FAQ](https://github.com/w-okada/voice-changer/blob/master/.github/FAQ.md) before making a bug report!
|
||||
- type: input
|
||||
id: vc-client-version
|
||||
attributes:
|
||||
label: Voice Changer Version
|
||||
description: Downloaded File Name (.zip)
|
||||
placeholder: MMVCServerSIO_xxx_yyyy-zzzz_v.x.x.x.x.zip
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: OS
|
||||
attributes:
|
||||
label: Operational System
|
||||
description: e.g. Windows 10, Ubuntu 20.04, MacOS Venture, MacOS Monterey, etc...
|
||||
placeholder: Windows 10
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: GPU
|
||||
attributes:
|
||||
label: GPU
|
||||
description: If you have no gpu, please input none.
|
||||
validations:
|
||||
required: true
|
||||
- type: checkboxes
|
||||
id: checks
|
||||
attributes:
|
||||
label: Read carefully and check the options
|
||||
options:
|
||||
- label: I've tried to Clear Settings
|
||||
- label: Sample/Default Models are working
|
||||
- label: I've tried to change the Chunk Size
|
||||
- label: GUI was successfully launched
|
||||
- label: I've read the [tutorial](https://github.com/w-okada/voice-changer/blob/master/tutorials/tutorial_rvc_en_latest.md)
|
||||
- label: I've tried to extract to another folder (or re-extract) the .zip file
|
||||
- type: input
|
||||
id: vc-type
|
||||
attributes:
|
||||
label: Model Type
|
||||
description: MMVC, so-vits-rvc, RVC, DDSP-SVC
|
||||
placeholder: RVC
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: issue
|
||||
attributes:
|
||||
label: Issue Description
|
||||
description: Please provide as much reproducible information and logs as possible
|
||||
- type: textarea
|
||||
id: capture
|
||||
attributes:
|
||||
label: Application Screenshot
|
||||
description: Please provide a screenshot of your application so we can see your settings (you can paste or drag-n-drop)
|
||||
- type: textarea
|
||||
id: logs-on-terminal
|
||||
attributes:
|
||||
label: Logs on console
|
||||
description: Copy and paste the log on your console here
|
||||
validations:
|
||||
required: true
|
82
.github/ISSUE_TEMPLATE/issue_for_v2.yaml
vendored
Normal file
@ -0,0 +1,82 @@
|
||||
name: Issue or Bug Report for v.2.x.x
|
||||
description: Please provide as much detail as possible to convey the history of your problem.
|
||||
title: "[ISSUE for v2]: "
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: Please read our [FAQ](https://github.com/w-okada/voice-changer/blob/master/.github/FAQ.md) before making a bug report!
|
||||
- type: input
|
||||
id: vc-client-version
|
||||
attributes:
|
||||
label: Voice Changer Version
|
||||
description: Downloaded File Name (.zip)
|
||||
placeholder: vcclient_win_std_x.y.x.zip, vcclient_win_cuda_torch_cuda_x.y.x.zip, or so
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: OS
|
||||
attributes:
|
||||
label: Operational System
|
||||
description: e.g. Windows 10, Ubuntu 20.04, MacOS Venture, MacOS Monterey, etc...
|
||||
placeholder: Windows 10
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: GPU
|
||||
attributes:
|
||||
label: GPU
|
||||
description: If you have no gpu, please input none.
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: CUDA
|
||||
attributes:
|
||||
label: CUDA Version
|
||||
description: If you have nvidia gpu, please input version of cuda. Otherwise, please input none.
|
||||
validations:
|
||||
required: true
|
||||
- type: checkboxes
|
||||
id: checks
|
||||
attributes:
|
||||
label: Read carefully and check the options
|
||||
options:
|
||||
- label: If you use win_cuda_torch_cuda edition, setup cuda? [see here](https://onnxruntime.ai/docs/execution-providers/CUDA-ExecutionProvider.html#requirements)
|
||||
- label: If you use win_cuda edition, setup cuda and cudnn? [see here](https://onnxruntime.ai/docs/execution-providers/CUDA-ExecutionProvider.html#requirements)
|
||||
- label: If you use mac edition, client is not launched automatically. Use chrome to open application.?
|
||||
- label: I've tried to change the Chunk Size
|
||||
- label: I've tried to set the Index to zero
|
||||
- label: I've read the [tutorial](https://github.com/w-okada/voice-changer/blob/master/tutorials/tutorial_rvc_en_latest.md)
|
||||
- label: I've tried to extract to another folder (or re-extract) the .zip file
|
||||
- type: dropdown
|
||||
id: sample-model-work
|
||||
attributes:
|
||||
label: Does pre-installed model work?
|
||||
options:
|
||||
- "No"
|
||||
- "YES"
|
||||
default: 0
|
||||
- type: input
|
||||
id: vc-type
|
||||
attributes:
|
||||
label: Model Type
|
||||
description: MMVC, so-vits-rvc, RVC, DDSP-SVC
|
||||
placeholder: RVC
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: issue
|
||||
attributes:
|
||||
label: Issue Description
|
||||
description: Please provide as much reproducible information and logs as possible
|
||||
- type: textarea
|
||||
id: capture
|
||||
attributes:
|
||||
label: Application Screenshot
|
||||
description: Please provide a screenshot of your application so we can see your settings (you can paste or drag-n-drop)
|
||||
- type: textarea
|
||||
id: logs-on-terminal
|
||||
attributes:
|
||||
label: Logs on console
|
||||
description: Copy and paste the log on your console here
|
||||
validations:
|
||||
required: true
|
15
.github/ISSUE_TEMPLATE/question.yaml
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
情報なしの質問が来てしまうので、このフォームを一時的に無効にする。
|
||||
|
||||
name: Question or Other
|
||||
description: Do you any question? Use this template
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: We are always working to make our software better, so please be pacient and wait for a response
|
||||
- type: textarea
|
||||
id: question
|
||||
attributes:
|
||||
label: Description
|
||||
description: What is your question? (or other non-related to bugs/feature-request)
|
||||
validations:
|
||||
required: true
|
36
.github/workflows/cla.yml
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
name: "CLA Assistant"
|
||||
on:
|
||||
issue_comment:
|
||||
types: [created]
|
||||
pull_request_target:
|
||||
types: [opened, closed, synchronize]
|
||||
|
||||
jobs:
|
||||
CLAssistant:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: "CLA Assistant"
|
||||
if: (github.event.comment.body == 'recheck' || github.event.comment.body == 'I have read the CLA Document and I hereby sign the CLA') || github.event_name == 'pull_request_target'
|
||||
# Beta Release
|
||||
uses: cla-assistant/github-action@v2.1.3-beta
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
# the below token should have repo scope and must be manually added by you in the repository's secret
|
||||
PERSONAL_ACCESS_TOKEN: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
|
||||
with:
|
||||
path-to-signatures: "signatures/version1/cla.json"
|
||||
path-to-document: "https://raw.githubusercontent.com/w-okada/voice-changer/master/LICENSE-CLA" # e.g. a CLA or a DCO document
|
||||
# branch should not be protected
|
||||
branch: "master"
|
||||
#allowlist: user1,bot*
|
||||
|
||||
#below are the optional inputs - If the optional inputs are not given, then default values will be taken
|
||||
#remote-organization-name: enter the remote organization name where the signatures should be stored (Default is storing the signatures in the same repository)
|
||||
#remote-repository-name: enter the remote repository name where the signatures should be stored (Default is storing the signatures in the same repository)
|
||||
#create-file-commit-message: 'For example: Creating file for storing CLA Signatures'
|
||||
#signed-commit-message: 'For example: $contributorName has signed the CLA in #$pullRequestNo'
|
||||
#custom-notsigned-prcomment: 'pull request comment with Introductory message to ask new contributors to sign'
|
||||
#custom-pr-sign-comment: 'The signature to be committed in order to sign the CLA'
|
||||
#custom-allsigned-prcomment: 'pull request comment when all contributors has signed, defaults to **CLA Assistant Lite bot** All Contributors have signed the CLA.'
|
||||
#lock-pullrequest-aftermerge: false - if you don't want this bot to automatically lock the pull request after merging (default - true)
|
||||
#use-dco-flag: true - If you are using DCO instead of CLA
|
66
.gitignore
vendored
@ -1,17 +1,77 @@
|
||||
tmp
|
||||
dummy
|
||||
node_modules
|
||||
__pycache__
|
||||
|
||||
server/upload_dir/
|
||||
server/MMVC_Trainer/
|
||||
server/MMVC_Client/
|
||||
server/MMVC_Client_v13/
|
||||
server/MMVC_Client_v15/
|
||||
server/so-vits-svc-40/
|
||||
server/so-vits-svc-40v2/
|
||||
server/DDSP-SVC/
|
||||
server/RVC/
|
||||
server/keys
|
||||
server/info
|
||||
server/in.wav
|
||||
server/out.wav
|
||||
server/G_*.pth
|
||||
server/train_config.json
|
||||
server/stored_setting.json
|
||||
# v.1.3.xテスト用モデルフォルダ
|
||||
server/v13
|
||||
|
||||
server/model_hubert
|
||||
server/model_so-vits-svc-40v2_tsukuyomi/
|
||||
server/model_so-vits-svc-40v2_amitaro/
|
||||
server/model_so-vits-svc-40/
|
||||
server/model_so-vits-svc-40_mahiro/
|
||||
server/model_so-vits-svc-40_amitaro/
|
||||
server/model_so-vits-svc-40_tsukuyomi/
|
||||
server/model_so-vits-svc-40_kikotokurage
|
||||
model_DDSP-SVC/
|
||||
server/model_sovits
|
||||
server/test
|
||||
|
||||
server/memo.md
|
||||
|
||||
client/lib/dist
|
||||
client/lib/worklet/dist
|
||||
client/demo/public/models
|
||||
client/demo/public/models_
|
||||
client/demo/dist/models
|
||||
client/demo/dist_web
|
||||
client/demo/src/001_provider/backup
|
||||
# client/demo/dist/ # demo用に残す
|
||||
|
||||
docker/cudnn/
|
||||
docker/cudnn/
|
||||
|
||||
server/pretrain/
|
||||
server/weights/
|
||||
server/model_dir/
|
||||
server/model_dir2/
|
||||
server/weights_/
|
||||
server/weights__/
|
||||
server/models/
|
||||
server/samples.json
|
||||
server/samples_0003_t.json
|
||||
server/samples_0003_o.json
|
||||
server/samples_0003_t2.json
|
||||
server/samples_0003_o2.json
|
||||
server/samples_0003_d2.json
|
||||
server/samples_0004_t.json
|
||||
server/samples_0004_o.json
|
||||
server/samples_0004_d.json
|
||||
|
||||
server/test_official_v1_v2.json
|
||||
server/test_ddpn_v1_v2.json
|
||||
server/vcclient.log
|
||||
start_trainer.sh
|
||||
|
||||
# venv
|
||||
venv/
|
||||
|
||||
|
||||
beatrice_internal_api.cp310-win_amd64.pyd
|
||||
108_average_110b_10.bin
|
||||
|
||||
server/model_dir_static/Beatrice-JVS
|
||||
|
9
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
"files.associations": {
|
||||
"*.css": "postcss"
|
||||
},
|
||||
"workbench.colorCustomizations": {
|
||||
"tab.activeBackground": "#65952acc"
|
||||
}
|
||||
}
|
||||
|
44
Checklist.md
@ -1,44 +0,0 @@
|
||||
# Release Check List
|
||||
## Run
|
||||
- [ ] Anaconda on Linux
|
||||
- [ ] Docker on Linux
|
||||
- [ ] Anaconda on WSL2
|
||||
- [ ] Docker on WSL2
|
||||
- [ ] Colab simple
|
||||
- [ ] Colab normal
|
||||
- [ ] Windows exe
|
||||
- [ ] Mac(M1)
|
||||
|
||||
## Doc
|
||||
- [ ] Readme
|
||||
- [ ] Wiki
|
||||
- [ ] Zenn
|
||||
|
||||
|
||||
# Memo
|
||||
## Release Process
|
||||
一通り開発が終わったと思ったら.
|
||||
|
||||
(1) Dockerを生成
|
||||
```
|
||||
npm run build:docker
|
||||
npm run push:docker
|
||||
```
|
||||
Tagをメモ。
|
||||
|
||||
(2) start2.shを編集
|
||||
メモしたTagを貼り付け。
|
||||
```
|
||||
bash start2.sh
|
||||
```
|
||||
|
||||
(3) exeファイル作成
|
||||
(3-1) Win
|
||||
・環境変数にリリースバージョンを設定
|
||||
・pipenv
|
||||
|
||||
(4) Readmeにリンクをはる
|
||||
|
||||
(5) Branch 解除。Tag化
|
||||
|
||||
(6) Colabチェック
|
1
Hina_Mod_Kaggle_Real_Time_Voice_Changer.ipynb
Normal file
351
Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb
Normal file
@ -0,0 +1,351 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "view-in-github",
|
||||
"colab_type": "text"
|
||||
},
|
||||
"source": [
|
||||
"<a href=\"https://colab.research.google.com/github/hinabl/voice-changer-colab/blob/master/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "Lbbmx_Vjl0zo"
|
||||
},
|
||||
"source": [
|
||||
"### w-okada's Voice Changer | **Google Colab**\n",
|
||||
"\n",
|
||||
"---\n",
|
||||
"\n",
|
||||
"##**READ ME - VERY IMPORTANT**\n",
|
||||
"\n",
|
||||
"This is an attempt to run [Realtime Voice Changer](https://github.com/w-okada/voice-changer) on Google Colab, still not perfect but is totally usable, you can use the following settings for better results:\n",
|
||||
"\n",
|
||||
"If you're using a index: `f0: RMVPE_ONNX | Chunk: 112 or higher | Extra: 8192`\\\n",
|
||||
"If you're not using a index: `f0: RMVPE_ONNX | Chunk: 96 or higher | Extra: 16384`\\\n",
|
||||
"**Don't forget to select your Colab GPU in the GPU field (<b>Tesla T4</b>, for free users)*\n",
|
||||
"> Seems that PTH models performance better than ONNX for now, you can still try ONNX models and see if it satisfies you\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"*You can always [click here](https://rentry.co/VoiceChangerGuide#gpu-chart-for-known-working-chunkextra\n",
|
||||
") to check if these settings are up-to-date*\n",
|
||||
"<br><br>\n",
|
||||
"\n",
|
||||
"---\n",
|
||||
"\n",
|
||||
"###Always use Colab GPU (**VERY VERY VERY IMPORTANT!**)\n",
|
||||
"You need to use a Colab GPU so the Voice Changer can work faster and better\\\n",
|
||||
"Use the menu above and click on **Runtime** » **Change runtime** » **Hardware acceleration** to select a GPU (**T4 is the free one**)\n",
|
||||
"\n",
|
||||
"---\n",
|
||||
"\n",
|
||||
"<br>\n",
|
||||
"\n",
|
||||
"# **Credits and Support**\n",
|
||||
"Realtime Voice Changer by [w-okada](https://github.com/w-okada)\\\n",
|
||||
"Colab files updated by [rafacasari](https://github.com/Rafacasari)\\\n",
|
||||
"Recommended settings by [Raven](https://github.com/ravencutie21)\\\n",
|
||||
"Modified again by [Hina](https://huggingface.co/HinaBl)\n",
|
||||
"\n",
|
||||
"Need help? [AI Hub Discord](https://discord.gg/aihub) » ***#help-realtime-vc***\n",
|
||||
"\n",
|
||||
"---"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "86wTFmqsNMnD",
|
||||
"cellView": "form"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"#=================Updated=================\n",
|
||||
"# @title **[1]** Clone repository and install dependencies\n",
|
||||
"# @markdown This first step will download the latest version of Voice Changer and install the dependencies. **It can take some time to complete.**\n",
|
||||
"import os\n",
|
||||
"import time\n",
|
||||
"import subprocess\n",
|
||||
"import threading\n",
|
||||
"import shutil\n",
|
||||
"import base64\n",
|
||||
"import codecs\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"#@markdown ---\n",
|
||||
"# @title **[Optional]** Connect to Google Drive\n",
|
||||
"# @markdown Using Google Drive can improve load times a bit and your models will be stored, so you don't need to re-upload every time that you use.\n",
|
||||
"\n",
|
||||
"Use_Drive=False #@param {type:\"boolean\"}\n",
|
||||
"\n",
|
||||
"from google.colab import drive\n",
|
||||
"\n",
|
||||
"if Use_Drive==True:\n",
|
||||
" if not os.path.exists('/content/drive'):\n",
|
||||
" drive.mount('/content/drive')\n",
|
||||
"\n",
|
||||
" %cd /content/drive/MyDrive\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"externalgit=codecs.decode('uggcf://tvguho.pbz/j-bxnqn/ibvpr-punatre.tvg','rot_13')\n",
|
||||
"rvctimer=codecs.decode('uggcf://tvguho.pbz/uvanoy/eipgvzre.tvg','rot_13')\n",
|
||||
"pathloc=codecs.decode('ibvpr-punatre','rot_13')\n",
|
||||
"\n",
|
||||
"from IPython.display import clear_output, Javascript\n",
|
||||
"\n",
|
||||
"def update_timer_and_print():\n",
|
||||
" global timer\n",
|
||||
" while True:\n",
|
||||
" hours, remainder = divmod(timer, 3600)\n",
|
||||
" minutes, seconds = divmod(remainder, 60)\n",
|
||||
" timer_str = f'{hours:02}:{minutes:02}:{seconds:02}'\n",
|
||||
" print(f'\\rTimer: {timer_str}', end='', flush=True) # Print without a newline\n",
|
||||
" time.sleep(1)\n",
|
||||
" timer += 1\n",
|
||||
"timer = 0\n",
|
||||
"threading.Thread(target=update_timer_and_print, daemon=True).start()\n",
|
||||
"\n",
|
||||
"!pip install colorama --quiet\n",
|
||||
"from colorama import Fore, Style\n",
|
||||
"\n",
|
||||
"print(f\"{Fore.CYAN}> Cloning the repository...{Style.RESET_ALL}\")\n",
|
||||
"!git clone --depth 1 $externalgit &> /dev/null\n",
|
||||
"print(f\"{Fore.GREEN}> Successfully cloned the repository!{Style.RESET_ALL}\")\n",
|
||||
"%cd $pathloc/server/\n",
|
||||
"\n",
|
||||
"# Read the content of the file\n",
|
||||
"file_path = '../client/demo/dist/assets/gui_settings/version.txt'\n",
|
||||
"\n",
|
||||
"with open(file_path, 'r') as file:\n",
|
||||
" file_content = file.read()\n",
|
||||
"\n",
|
||||
"# Replace the specific text\n",
|
||||
"text_to_replace = \"-.-.-.-\"\n",
|
||||
"new_text = \"Google.Colab\" # New text to replace the specific text\n",
|
||||
"\n",
|
||||
"modified_content = file_content.replace(text_to_replace, new_text)\n",
|
||||
"\n",
|
||||
"# Write the modified content back to the file\n",
|
||||
"with open(file_path, 'w') as file:\n",
|
||||
" file.write(modified_content)\n",
|
||||
"\n",
|
||||
"print(f\"Text '{text_to_replace}' has been replaced with '{new_text}' in the file.\")\n",
|
||||
"\n",
|
||||
"print(f\"{Fore.CYAN}> Installing libportaudio2...{Style.RESET_ALL}\")\n",
|
||||
"!apt-get -y install libportaudio2 -qq\n",
|
||||
"\n",
|
||||
"!sed -i '/torch==/d' requirements.txt\n",
|
||||
"!sed -i '/torchaudio==/d' requirements.txt\n",
|
||||
"!sed -i '/numpy==/d' requirements.txt\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"print(f\"{Fore.CYAN}> Installing pre-dependencies...{Style.RESET_ALL}\")\n",
|
||||
"# Install dependencies that are missing from requirements.txt and pyngrok\n",
|
||||
"!pip install faiss-gpu fairseq pyngrok --quiet\n",
|
||||
"!pip install pyworld --no-build-isolation --quiet\n",
|
||||
"# Install webstuff\n",
|
||||
"import asyncio\n",
|
||||
"import re\n",
|
||||
"!pip install playwright\n",
|
||||
"!playwright install\n",
|
||||
"!playwright install-deps\n",
|
||||
"!pip install nest_asyncio\n",
|
||||
"from playwright.async_api import async_playwright\n",
|
||||
"print(f\"{Fore.CYAN}> Installing dependencies from requirements.txt...{Style.RESET_ALL}\")\n",
|
||||
"!pip install -r requirements.txt --quiet\n",
|
||||
"clear_output()\n",
|
||||
"print(f\"{Fore.GREEN}> Successfully installed all packages!{Style.RESET_ALL}\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"#@title **[Optional]** Upload a voice model (Run this before running the Voice Changer)\n",
|
||||
"import os\n",
|
||||
"import json\n",
|
||||
"from IPython.display import Image\n",
|
||||
"import requests\n",
|
||||
"\n",
|
||||
"model_slot = \"0\" #@param ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '36', '37', '38', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '50', '51', '52', '53', '54', '55', '56', '57', '58', '59', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '70', '71', '72', '73', '74', '75', '76', '77', '78', '79', '80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '90', '91', '92', '93', '94', '95', '96', '97', '98', '99', '100', '101', '102', '103', '104', '105', '106', '107', '108', '109', '110', '111', '112', '113', '114', '115', '116', '117', '118', '119', '120', '121', '122', '123', '124', '125', '126', '127', '128', '129', '130', '131', '132', '133', '134', '135', '136', '137', '138', '139', '140', '141', '142', '143', '144', '145', '146', '147', '148', '149', '150', '151', '152', '153', '154', '155', '156', '157', '158', '159', '160', '161', '162', '163', '164', '165', '166', '167', '168', '169', '170', '171', '172', '173', '174', '175', '176', '177', '178', '179', '180', '181', '182', '183', '184', '185', '186', '187', '188', '189', '190', '191', '192', '193', '194', '195', '196', '197', '198', '199']\n",
|
||||
"\n",
|
||||
"!rm -rf model_dir/$model_slot\n",
|
||||
"#@markdown **[Optional]** Add an icon to the model\n",
|
||||
"icon_link = \"https://cdn.donmai.us/sample/12/57/__rin_penrose_idol_corp_drawn_by_juu_ame__sample-12579843de9487cf2db82058ba5e77d4.jpg\" #@param {type:\"string\"}\n",
|
||||
"icon_link = '\"'+icon_link+'\"'\n",
|
||||
"!mkdir model_dir\n",
|
||||
"!mkdir model_dir/$model_slot\n",
|
||||
"#@markdown Put your model's download link here `(must be a zip file)` only supports **weights.gg** & **huggingface.co**\n",
|
||||
"model_link = \"https://huggingface.co/HinaBl/Rin-Penrose/resolve/main/RinPenrose600.zip?download=true\" #@param {type:\"string\"}\n",
|
||||
"\n",
|
||||
"if model_link.startswith(\"https://www.weights.gg\") or model_link.startswith(\"https://weights.gg\"):\n",
|
||||
" weights_code = requests.get(\"https://pastebin.com/raw/ytHLr8h0\").text\n",
|
||||
" exec(weights_code)\n",
|
||||
"else:\n",
|
||||
" model_link = model_link\n",
|
||||
"\n",
|
||||
"model_link = '\"'+model_link+'\"'\n",
|
||||
"!curl -L $model_link > model.zip\n",
|
||||
"\n",
|
||||
"# Conditionally set the iconFile based on whether icon_link is empty\n",
|
||||
"if icon_link:\n",
|
||||
" iconFile = \"icon.png\"\n",
|
||||
" !curl -L $icon_link > model_dir/$model_slot/icon.png\n",
|
||||
"else:\n",
|
||||
" iconFile = \"\"\n",
|
||||
" print(\"icon_link is empty, so no icon file will be downloaded.\")\n",
|
||||
"\n",
|
||||
"!unzip model.zip -d model_dir/$model_slot\n",
|
||||
"\n",
|
||||
"!mv model_dir/$model_slot/*/* model_dir/$model_slot/\n",
|
||||
"!rm -rf model_dir/$model_slot/*/\n",
|
||||
"#@markdown **Model Voice Convertion Setting**\n",
|
||||
"Tune = 12 #@param {type:\"slider\",min:-50,max:50,step:1}\n",
|
||||
"Index = 0 #@param {type:\"slider\",min:0,max:1,step:0.1}\n",
|
||||
"\n",
|
||||
"param_link = \"\"\n",
|
||||
"if param_link == \"\":\n",
|
||||
" paramset = requests.get(\"https://pastebin.com/raw/SAKwUCt1\").text\n",
|
||||
" exec(paramset)\n",
|
||||
"\n",
|
||||
"clear_output()\n",
|
||||
"print(\"\\033[93mModel with the name of \"+model_name+\" has been Imported to slot \"+model_slot)"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "_ZtbKUVUgN3G",
|
||||
"cellView": "form"
|
||||
},
|
||||
"execution_count": null,
|
||||
"outputs": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "lLWQuUd7WW9U",
|
||||
"cellView": "form"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"\n",
|
||||
"#=======================Updated=========================\n",
|
||||
"\n",
|
||||
"# @title Start Server **using ngrok**\n",
|
||||
"# @markdown This cell will start the server, the first time that you run it will download the models, so it can take a while (~1-2 minutes)\n",
|
||||
"\n",
|
||||
"# @markdown ---\n",
|
||||
"# @markdown You'll need a ngrok account, but <font color=green>**it's free**</font> and easy to create!\n",
|
||||
"# @markdown ---\n",
|
||||
"# @markdown **1** - Create a <font color=green>**free**</font> account at [ngrok](https://dashboard.ngrok.com/signup) or **login with Google/Github account**\\\n",
|
||||
"# @markdown **2** - If you didn't logged in with Google/Github, you will need to **verify your e-mail**!\\\n",
|
||||
"# @markdown **3** - Click [this link](https://dashboard.ngrok.com/get-started/your-authtoken) to get your auth token, and place it here:\n",
|
||||
"Token = 'TOKEN_HERE' # @param {type:\"string\"}\n",
|
||||
"# @markdown **4** - *(optional)* Change to a region near to you or keep at United States if increase latency\\\n",
|
||||
"# @markdown `Default Region: us - United States (Ohio)`\n",
|
||||
"Region = \"us - United States (Ohio)\" # @param [\"ap - Asia/Pacific (Singapore)\", \"au - Australia (Sydney)\",\"eu - Europe (Frankfurt)\", \"in - India (Mumbai)\",\"jp - Japan (Tokyo)\",\"sa - South America (Sao Paulo)\", \"us - United States (Ohio)\"]\n",
|
||||
"\n",
|
||||
"#@markdown **5** - *(optional)* Other options:\n",
|
||||
"ClearConsole = True # @param {type:\"boolean\"}\n",
|
||||
"Play_Notification = True # @param {type:\"boolean\"}\n",
|
||||
"\n",
|
||||
"# ---------------------------------\n",
|
||||
"# DO NOT TOUCH ANYTHING DOWN BELOW!\n",
|
||||
"# ---------------------------------\n",
|
||||
"\n",
|
||||
"%cd $pathloc/server/\n",
|
||||
"\n",
|
||||
"from pyngrok import conf, ngrok\n",
|
||||
"MyConfig = conf.PyngrokConfig()\n",
|
||||
"MyConfig.auth_token = Token\n",
|
||||
"MyConfig.region = Region[0:2]\n",
|
||||
"#conf.get_default().authtoken = Token\n",
|
||||
"#conf.get_default().region = Region\n",
|
||||
"conf.set_default(MyConfig);\n",
|
||||
"\n",
|
||||
"import subprocess, threading, time, socket, urllib.request\n",
|
||||
"PORT = 8000\n",
|
||||
"\n",
|
||||
"from pyngrok import ngrok\n",
|
||||
"ngrokConnection = ngrok.connect(PORT)\n",
|
||||
"public_url = ngrokConnection.public_url\n",
|
||||
"\n",
|
||||
"from IPython.display import clear_output\n",
|
||||
"from IPython.display import Audio, display\n",
|
||||
"def play_notification_sound():\n",
|
||||
" display(Audio(url='https://raw.githubusercontent.com/hinabl/rmvpe-ai-kaggle/main/custom/audios/notif.mp3', autoplay=True))\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def wait_for_server():\n",
|
||||
" while True:\n",
|
||||
" time.sleep(0.5)\n",
|
||||
" sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n",
|
||||
" result = sock.connect_ex(('127.0.0.1', PORT))\n",
|
||||
" if result == 0:\n",
|
||||
" break\n",
|
||||
" sock.close()\n",
|
||||
" if ClearConsole:\n",
|
||||
" clear_output()\n",
|
||||
" print(\"--------- SERVER READY! ---------\")\n",
|
||||
" print(\"Your server is available at:\")\n",
|
||||
" print(public_url)\n",
|
||||
" print(\"---------------------------------\")\n",
|
||||
" if Play_Notification==True:\n",
|
||||
" play_notification_sound()\n",
|
||||
"\n",
|
||||
"threading.Thread(target=wait_for_server, daemon=True).start()\n",
|
||||
"\n",
|
||||
"mainpy=codecs.decode('ZZIPFreireFVB.cl','rot_13')\n",
|
||||
"\n",
|
||||
"!python3 $mainpy \\\n",
|
||||
" -p {PORT} \\\n",
|
||||
" --https False \\\n",
|
||||
" --content_vec_500 pretrain/checkpoint_best_legacy_500.pt \\\n",
|
||||
" --content_vec_500_onnx pretrain/content_vec_500.onnx \\\n",
|
||||
" --content_vec_500_onnx_on true \\\n",
|
||||
" --hubert_base pretrain/hubert_base.pt \\\n",
|
||||
" --hubert_base_jp pretrain/rinna_hubert_base_jp.pt \\\n",
|
||||
" --hubert_soft pretrain/hubert/hubert-soft-0d54a1f4.pt \\\n",
|
||||
" --nsf_hifigan pretrain/nsf_hifigan/model \\\n",
|
||||
" --crepe_onnx_full pretrain/crepe_onnx_full.onnx \\\n",
|
||||
" --crepe_onnx_tiny pretrain/crepe_onnx_tiny.onnx \\\n",
|
||||
" --rmvpe pretrain/rmvpe.pt \\\n",
|
||||
" --model_dir model_dir \\\n",
|
||||
" --samples samples.json\n",
|
||||
"\n",
|
||||
"ngrok.disconnect(ngrokConnection.public_url)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"\n",
|
||||
""
|
||||
],
|
||||
"metadata": {
|
||||
"id": "2Uu1sTSwTc7q"
|
||||
}
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"provenance": [],
|
||||
"private_outputs": true,
|
||||
"gpuType": "T4",
|
||||
"include_colab_link": true
|
||||
},
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
},
|
||||
"accelerator": "GPU"
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 0
|
||||
}
|
99
Kaggle_RealtimeVoiceChanger.ipynb
Normal file
@ -0,0 +1,99 @@
|
||||
{
|
||||
"metadata":{
|
||||
"kernelspec":{
|
||||
"language":"python",
|
||||
"display_name":"Python 3",
|
||||
"name":"python3"
|
||||
},
|
||||
"language_info":{
|
||||
"name":"python",
|
||||
"version":"3.10.12",
|
||||
"mimetype":"text/x-python",
|
||||
"codemirror_mode":{
|
||||
"name":"ipython",
|
||||
"version":3
|
||||
},
|
||||
"pygments_lexer":"ipython3",
|
||||
"nbconvert_exporter":"python",
|
||||
"file_extension":".py"
|
||||
}
|
||||
},
|
||||
"nbformat_minor":4,
|
||||
"nbformat":4,
|
||||
"cells":[
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "view-in-github",
|
||||
"colab_type": "text"
|
||||
},
|
||||
"source": [
|
||||
"<a href=\"https://www.kaggle.com/code/rafacasari/wokada-voice-changer\" target=\"_parent\"><img src=\"https://img.shields.io/badge/Open%20In%20Kaggle-035a7d?style=for-the-badge&logo=kaggle&logoColor=white\" alt=\"Open In Colab\"/></a>"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type":"markdown",
|
||||
"source":"### [w-okada's Voice Changer](https://github.com/w-okada/voice-changer) | **Kaggle**\n\n---\n\n## **⬇ VERY IMPORTANT ⬇**\n\nYou can use the following settings for better results:\n\nIf you're using a index: `f0: RMVPE_ONNX | Chunk: 112 or higher | Extra: 8192`<br>\nIf you're not using a index: `f0: RMVPE_ONNX | Chunk: 96 or higher | Extra: 16384`<br>\n**Don't forget to select a GPU in the GPU field, <b>NEVER</b> use CPU!\n> Seems that PTH models performance better than ONNX for now, you can still try ONNX models and see if it satisfies you\n\n\n*You can always [click here](https://github.com/YunaOneeChan/Voice-Changer-Settings) to check if these settings are up-to-date*\n\n---\n**Credits**<br>\nRealtime Voice Changer by [w-okada](https://github.com/w-okada)<br>\nNotebook files updated by [rafacasari](https://github.com/Rafacasari)<br>\nRecommended settings by [YunaOneeChan](https://github.com/YunaOneeChan)\n\n**Need help?** [AI Hub Discord](https://discord.gg/aihub) » ***#help-realtime-vc***\n\n---",
|
||||
"metadata":{
|
||||
"id":"Lbbmx_Vjl0zo"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type":"markdown",
|
||||
"source":"# Kaggle Tutorial\nRunning this notebook can be a bit complicated.\\\nAfter created your Kaggle account, you'll need to **verify your phone number** to be able to use Internet Connection and GPUs.\\\nFollow the instructions on the image below.\n\n## <font color=blue>*You can use <b>GPU P100</b> instead of GPU T4, some people are telling that <b>P100 is better</b>.*</font>\n",
|
||||
"metadata":{
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type":"markdown",
|
||||
"source":"# Clone repository and install dependencies\nThis first step will download the latest version of Voice Changer and install the dependencies. **It will take some time to complete.**",
|
||||
"metadata":{
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type":"code",
|
||||
"source":"# This will make that we're on the right folder before installing\n%cd /kaggle/working/\n\n!pip install colorama --quiet\nfrom colorama import Fore, Style\nimport os\n\nprint(f\"{Fore.CYAN}> Cloning the repository...{Style.RESET_ALL}\")\n!git clone https://github.com/w-okada/voice-changer.git --quiet\nprint(f\"{Fore.GREEN}> Successfully cloned the repository!{Style.RESET_ALL}\")\n%cd voice-changer/server/\n\nprint(f\"{Fore.CYAN}> Installing libportaudio2...{Style.RESET_ALL}\")\n!apt-get -y install libportaudio2 -qq\n\nprint(f\"{Fore.CYAN}> Installing pre-dependencies...{Style.RESET_ALL}\")\n# Install dependencies that are missing from requirements.txt and pyngrok\n!pip install faiss-gpu fairseq pyngrok --quiet \n!pip install pyworld --no-build-isolation --quiet\nprint(f\"{Fore.CYAN}> Installing dependencies from requirements.txt...{Style.RESET_ALL}\")\n!pip install -r requirements.txt --quiet\n\n# Download the default settings ^-^\nif not os.path.exists(\"/kaggle/working/voice-changer/server/stored_setting.json\"):\n !wget -q https://gist.githubusercontent.com/Rafacasari/d820d945497a01112e1a9ba331cbad4f/raw/8e0a426c22688b05dd9c541648bceab27e422dd6/kaggle_setting.json -O /kaggle/working/voice-changer/server/stored_setting.json\nprint(f\"{Fore.GREEN}> Successfully installed all packages!{Style.RESET_ALL}\")\n\nprint(f\"{Fore.GREEN}> You can safely ignore the dependency conflict errors, it's a error from Kaggle and don't interfer on Voice Changer!{Style.RESET_ALL}\")",
|
||||
"metadata":{
|
||||
"id":"86wTFmqsNMnD",
|
||||
"cellView":"form",
|
||||
"_kg_hide-output":false,
|
||||
"execution":{
|
||||
"iopub.status.busy":"2023-09-14T04:01:17.308284Z",
|
||||
"iopub.execute_input":"2023-09-14T04:01:17.308682Z",
|
||||
"iopub.status.idle":"2023-09-14T04:08:08.475375Z",
|
||||
"shell.execute_reply.started":"2023-09-14T04:01:17.308652Z",
|
||||
"shell.execute_reply":"2023-09-14T04:08:08.473827Z"
|
||||
},
|
||||
"trusted":true
|
||||
},
|
||||
"execution_count":0,
|
||||
"outputs":[
|
||||
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type":"markdown",
|
||||
"source":"# Start Server **using ngrok**\nThis cell will start the server, the first time that you run it will download the models, so it can take a while (~1-2 minutes)\n\n---\nYou'll need a ngrok account, but <font color=green>**it's free**</font> and easy to create!\n---\n**1** - Create a **free** account at [ngrok](https://dashboard.ngrok.com/signup)\\\n**2** - If you didn't logged in with Google or Github, you will need to **verify your e-mail**!\\\n**3** - Click [this link](https://dashboard.ngrok.com/get-started/your-authtoken) to get your auth token, and replace **YOUR_TOKEN_HERE** with your token.\\\n**4** - *(optional)* Change to a region near to you",
|
||||
"metadata":{
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type":"code",
|
||||
"source":"# ---------------------------------\n# SETTINGS\n# ---------------------------------\n\nToken = '2Tn2hbfLtw2ii6DHEJy7SsM1BjI_21G14MXSwz7qZSDL2Dv3B'\nClearConsole = True # Clear console after initialization. Set to False if you are having some error, then you will be able to report it.\nRegion = \"sa\" # Read the instructions below\n\n# You can change the region for a better latency, use only the abbreviation\n# Choose between this options: \n# us -> United States (Ohio)\n# ap -> Asia/Pacific (Singapore)\n# au -> Australia (Sydney)\n# eu -> Europe (Frankfurt)\n# in -> India (Mumbai)\n# jp -> Japan (Tokyo)\n# sa -> South America (Sao Paulo)\n\n# ---------------------------------\n# DO NOT TOUCH ANYTHING DOWN BELOW!\n# ---------------------------------\n\n%cd /kaggle/working/voice-changer/server\n \nfrom pyngrok import conf, ngrok\nMyConfig = conf.PyngrokConfig()\nMyConfig.auth_token = Token\nMyConfig.region = Region\n#conf.get_default().authtoken = Token\n#conf.get_default().region = Region\nconf.set_default(MyConfig);\n\nimport subprocess, threading, time, socket, urllib.request\nPORT = 8000\n\nfrom pyngrok import ngrok\nngrokConnection = ngrok.connect(PORT)\npublic_url = ngrokConnection.public_url\n\nfrom IPython.display import clear_output\n\ndef wait_for_server():\n while True:\n time.sleep(0.5)\n sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n result = sock.connect_ex(('127.0.0.1', PORT))\n if result == 0:\n break\n sock.close()\n if ClearConsole:\n clear_output()\n print(\"--------- SERVER READY! ---------\")\n print(\"Your server is available at:\")\n print(public_url)\n print(\"---------------------------------\")\n\nthreading.Thread(target=wait_for_server, daemon=True).start()\n\n!python3 MMVCServerSIO.py \\\n -p {PORT} \\\n --https False \\\n --content_vec_500 pretrain/checkpoint_best_legacy_500.pt \\\n --content_vec_500_onnx pretrain/content_vec_500.onnx \\\n --content_vec_500_onnx_on true \\\n --hubert_base pretrain/hubert_base.pt \\\n --hubert_base_jp pretrain/rinna_hubert_base_jp.pt \\\n --hubert_soft pretrain/hubert/hubert-soft-0d54a1f4.pt \\\n --nsf_hifigan pretrain/nsf_hifigan/model \\\n --crepe_onnx_full pretrain/crepe_onnx_full.onnx \\\n --crepe_onnx_tiny pretrain/crepe_onnx_tiny.onnx \\\n --rmvpe pretrain/rmvpe.pt \\\n --model_dir model_dir \\\n --samples samples.json\n\nngrok.disconnect(ngrokConnection.public_url)",
|
||||
"metadata":{
|
||||
"id":"lLWQuUd7WW9U",
|
||||
"cellView":"form",
|
||||
"_kg_hide-input":false,
|
||||
"scrolled":true,
|
||||
"trusted":true
|
||||
},
|
||||
"execution_count":null,
|
||||
"outputs":[
|
||||
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
70
LICENSE
@ -20,7 +20,6 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2022 Isle Tennos
|
||||
@ -63,4 +62,71 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
SOFTWARE.
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2023 liujing04
|
||||
Copyright (c) 2023 源文雨
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2023 yxlllc
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2023 yxlllc
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
27
LICENSE-CLA
Normal file
@ -0,0 +1,27 @@
|
||||
Contributor License Agreement
|
||||
|
||||
Copyright (c) 2022 Wataru Okada
|
||||
|
||||
本契約は、当社とあなた(以下、"貢献者"とします)の間で締結され、貢献者が当社に対してソフトウェアプロジェクト(以下、"プロジェクト"とします)に対する貢献(以下、"貢献"とします)を提供する際の条件を定めます。
|
||||
|
||||
1. 貢献者は、提供する貢献が、貢献者自身のオリジナルな作品であり、商標、著作権、特許、または他の知的財産権を侵害していないことを保証します。
|
||||
|
||||
2. 貢献者は、貢献を当社に対して無償で提供し、当社はそれを無制限に使用、複製、修正、公開、配布、サブライセンスを付与し、またその販売する権利を得ることに同意します。
|
||||
|
||||
3. 本契約が終了した場合でも、第 2 項で述べた権利は当社に留保されます。
|
||||
|
||||
4. 当社は貢献者の貢献を受け入れる義務を負わず、また貢献者に一切の補償をする義務を負わないことに貢献者は同意します。
|
||||
|
||||
5. 本契約は当社と貢献者双方の書面による合意により修正されることがあります。
|
||||
|
||||
"This Agreement is made between our Company and you (hereinafter referred to as "Contributor") and outlines the terms under which you provide your Contributions (hereinafter referred to as "Contributions") to our software project (hereinafter referred to as "Project").
|
||||
|
||||
1. You warrant that the Contributions you are providing are your original work and do not infringe any trademark, copyright, patent, or other intellectual property rights.
|
||||
|
||||
2. You agree to provide your Contributions to the Company for free, and the Company has the unlimited right to use, copy, modify, publish, distribute, and sublicense, and also sell the Contributions.
|
||||
|
||||
3. Even after the termination of this Agreement, the rights mentioned in the above clause will be retained by the Company.
|
||||
|
||||
4. The Company is under no obligation to accept your Contributions or to compensate you in any way for them, and you agree to this.
|
||||
|
||||
5. This Agreement may be modified by written agreement between the Company and the Contributor."
|
13
LICENSE-NOTICE
Normal file
@ -0,0 +1,13 @@
|
||||
1. Diffusion SVC, DDSP SVC は vocodeer は DiffSinger Community Vocoders を使用しています。次のリンクからライセンスをご確認ください。
|
||||
別のモデルを使用する場合は pretrain\\nsf_hifigan に設置してください。
|
||||
https://openvpi.github.io/vocoders/
|
||||
|
||||
Diffusion SVC and DDSP SVC uses DiffSinger Community Vocoders. Please check the license from the following link.
|
||||
Please place it on pretrain\\nsf_hifigan if you are using a different model.
|
||||
https://openvpi.github.io/vocoders/
|
||||
|
||||
2. Beatrice JVS Corpus Edition のライセンスについてはこちらを確認してください。
|
||||
[readme](https://github.com/w-okada/voice-changer/blob/master/server/voice_changer/Beatrice/)
|
||||
|
||||
Please check here for the license of the Beatrice JVS Corpus Edition.
|
||||
[readme](https://github.com/w-okada/voice-changer/blob/master/server/voice_changer/Beatrice/)
|
@ -1,334 +0,0 @@
|
||||
{
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 0,
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"provenance": [],
|
||||
"include_colab_link": true
|
||||
},
|
||||
"kernelspec": {
|
||||
"name": "python3",
|
||||
"display_name": "Python 3"
|
||||
},
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
},
|
||||
"gpuClass": "standard",
|
||||
"accelerator": "GPU"
|
||||
},
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "view-in-github",
|
||||
"colab_type": "text"
|
||||
},
|
||||
"source": [
|
||||
"<a href=\"https://colab.research.google.com/github/w-okada/voice-changer/blob/dev/MMVCTrainerFrontendDemo.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"Voice Changer Simple (デモ版)\n",
|
||||
"---\n",
|
||||
"\n",
|
||||
"このノートはVoice ChangerをColab上で動かすデモ版です。\n",
|
||||
"\n",
|
||||
"正式版はローカルPCのDocker上で動かすアプリケーションです。\n",
|
||||
"\n",
|
||||
"正式版は、多くの場合より少ないタイムラグで滑らかに音声を変換できます。\n",
|
||||
"\n",
|
||||
"詳細な使用方法はこちらの[リポジトリ](https://github.com/w-okada/voice-changer)からご確認ください。\n"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "Lbbmx_Vjl0zo"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"# GPUを確認\n",
|
||||
"GPUを用いたほうが高速に処理が行えます。\n",
|
||||
"\n",
|
||||
"下記のコマンドでGPUが確認できない場合は、上のメニューから\n",
|
||||
"\n",
|
||||
"「ランタイム」→「ランタイムの変更」→「ハードウェア アクセラレータ」\n",
|
||||
"\n",
|
||||
"でGPUを選択してください。"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "oUKi1NYMmXrr"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"# (1) GPUの確認\n",
|
||||
"!nvidia-smi"
|
||||
],
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"base_uri": "https://localhost:8080/"
|
||||
},
|
||||
"id": "vV1t7PBRm-o6",
|
||||
"outputId": "4f159c80-8114-4732-f5af-0856f7b5c39a"
|
||||
},
|
||||
"execution_count": 1,
|
||||
"outputs": [
|
||||
{
|
||||
"output_type": "stream",
|
||||
"name": "stdout",
|
||||
"text": [
|
||||
"Sat Dec 10 23:45:44 2022 \n",
|
||||
"+-----------------------------------------------------------------------------+\n",
|
||||
"| NVIDIA-SMI 460.32.03 Driver Version: 460.32.03 CUDA Version: 11.2 |\n",
|
||||
"|-------------------------------+----------------------+----------------------+\n",
|
||||
"| GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC |\n",
|
||||
"| Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. |\n",
|
||||
"| | | MIG M. |\n",
|
||||
"|===============================+======================+======================|\n",
|
||||
"| 0 Tesla T4 Off | 00000000:00:04.0 Off | 0 |\n",
|
||||
"| N/A 70C P0 31W / 70W | 0MiB / 15109MiB | 0% Default |\n",
|
||||
"| | | N/A |\n",
|
||||
"+-------------------------------+----------------------+----------------------+\n",
|
||||
" \n",
|
||||
"+-----------------------------------------------------------------------------+\n",
|
||||
"| Processes: |\n",
|
||||
"| GPU GI CI PID Type Process name GPU Memory |\n",
|
||||
"| ID ID Usage |\n",
|
||||
"|=============================================================================|\n",
|
||||
"| No running processes found |\n",
|
||||
"+-----------------------------------------------------------------------------+\n"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"# リポジトリのクローン\n",
|
||||
"リポジトリをクローンします"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "sLBfykjBnjWc"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"# (2) リポジトリのクローン\n",
|
||||
"!git clone --depth 1 https://github.com/w-okada/voice-changer.git -b dev\n",
|
||||
"%cd voice-changer/demo/\n",
|
||||
"\n",
|
||||
"!cp ../template/setting_mmvc_colab.json ../frontend/dist/assets/setting.json"
|
||||
],
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"base_uri": "https://localhost:8080/"
|
||||
},
|
||||
"id": "86wTFmqsNMnD",
|
||||
"outputId": "3f84319c-0365-442a-fa3a-0a8aea701926"
|
||||
},
|
||||
"execution_count": 2,
|
||||
"outputs": [
|
||||
{
|
||||
"output_type": "stream",
|
||||
"name": "stdout",
|
||||
"text": [
|
||||
"Cloning into 'voice-changer'...\n",
|
||||
"remote: Enumerating objects: 1029, done.\u001b[K\n",
|
||||
"remote: Counting objects: 100% (1029/1029), done.\u001b[K\n",
|
||||
"remote: Compressing objects: 100% (919/919), done.\u001b[K\n",
|
||||
"remote: Total 1029 (delta 21), reused 979 (delta 10), pack-reused 0\u001b[K\n",
|
||||
"Receiving objects: 100% (1029/1029), 71.87 MiB | 26.18 MiB/s, done.\n",
|
||||
"Resolving deltas: 100% (21/21), done.\n",
|
||||
"/content/voice-changer/demo\n"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"# モジュールのインストール\n",
|
||||
"\n",
|
||||
"必要なモジュールをインストールします。"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "8Na2PbLZSWgZ"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"# (3) 設定ファイルの確認\n",
|
||||
"!apt-get install -y espeak libsndfile1-dev &> /dev/null\n",
|
||||
"!pip install unidecode &> /dev/null\n",
|
||||
"!pip install phonemizer &> /dev/null\n",
|
||||
"!pip install retry &> /dev/null\n",
|
||||
"!pip install python-socketio &> /dev/null\n",
|
||||
"!pip install fastapi &> /dev/null\n",
|
||||
"!pip install python-multipart &> /dev/null\n",
|
||||
"!pip install uvicorn &> /dev/null\n",
|
||||
"!pip install websockets &> /dev/null\n",
|
||||
"!pip install pyOpenSSL &> /dev/null\n",
|
||||
"!pip install pyopenjtalk==0.2.0 &> /dev/null\n",
|
||||
"\n",
|
||||
"%cd MMVC_Trainer/monotonic_align/\n",
|
||||
"!python setup.py build_ext --inplace\n",
|
||||
"%cd ../../"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "LwZAAuqxX7yY",
|
||||
"outputId": "61526e29-97d9-4975-e921-4ca9ae5a153f",
|
||||
"colab": {
|
||||
"base_uri": "https://localhost:8080/"
|
||||
}
|
||||
},
|
||||
"execution_count": 3,
|
||||
"outputs": [
|
||||
{
|
||||
"output_type": "stream",
|
||||
"name": "stdout",
|
||||
"text": [
|
||||
"/content/voice-changer/demo/MMVC_Trainer/monotonic_align\n",
|
||||
"running build_ext\n",
|
||||
"building 'monotonic_align.core' extension\n",
|
||||
"creating build\n",
|
||||
"creating build/temp.linux-x86_64-3.8\n",
|
||||
"x86_64-linux-gnu-gcc -pthread -Wno-unused-result -Wsign-compare -DNDEBUG -g -fwrapv -O2 -Wall -g -fstack-protector-strong -Wformat -Werror=format-security -g -fwrapv -O2 -g -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -fPIC -I/usr/local/lib/python3.8/dist-packages/numpy/core/include -I/usr/include/python3.8 -c core.c -o build/temp.linux-x86_64-3.8/core.o\n",
|
||||
"x86_64-linux-gnu-gcc -pthread -shared -Wl,-O1 -Wl,-Bsymbolic-functions -Wl,-Bsymbolic-functions -g -fwrapv -O2 -Wl,-Bsymbolic-functions -g -fwrapv -O2 -g -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 build/temp.linux-x86_64-3.8/core.o -o /content/voice-changer/demo/MMVC_Trainer/monotonic_align/monotonic_align/core.cpython-38-x86_64-linux-gnu.so\n",
|
||||
"/content/voice-changer/demo\n"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"# サーバの起動\n",
|
||||
"\n",
|
||||
"サーバを起動します。(4-1)\n",
|
||||
"\n",
|
||||
"サーバの起動状況を確認します。(4-2) \n",
|
||||
"\n",
|
||||
"このセルは繰り返し実行することになるのでCtrl+Retでセルを実行してください。\n",
|
||||
"\n",
|
||||
"下記のようなテキストが表示されたら起動完了です。\n",
|
||||
"\n",
|
||||
"**`DEBUG:asyncio:Using selector: EpollSelector`**\n",
|
||||
"\n",
|
||||
"```\n",
|
||||
" Phase name:__main__\n",
|
||||
" PHASE3:__main__\n",
|
||||
" PHASE1:__main__\n",
|
||||
"Start MMVC SocketIO Server\n",
|
||||
" CONFIG:None, MODEL:None\n",
|
||||
"DEBUG:asyncio:Using selector: EpollSelector\n",
|
||||
"```\n",
|
||||
"\n"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "-_2OcN9Borke"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"# (4-1) サーバの起動\n",
|
||||
"import random\n",
|
||||
"PORT = 10000 + random.randint(1, 9999)\n",
|
||||
"LOG_FILE = f\"LOG_FILE_{PORT}\"\n",
|
||||
"\n",
|
||||
"get_ipython().system_raw(f'python3 MMVCServerSIO.py -p {PORT} --colab True >{LOG_FILE} 2>&1 &')\n",
|
||||
"#print(f\"PORT:{PORT}, LOG_FILE:{LOG_FILE}\")"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "G-nMdPxEW1rc"
|
||||
},
|
||||
"execution_count": 4,
|
||||
"outputs": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"# (4-2) サーバの起動確認\n",
|
||||
"!sleep 5\n",
|
||||
"!tail -20 {LOG_FILE}"
|
||||
],
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"base_uri": "https://localhost:8080/"
|
||||
},
|
||||
"id": "chu06KpAjEK6",
|
||||
"outputId": "51b4979c-91b7-4c95-eb4b-40ea001042a9"
|
||||
},
|
||||
"execution_count": 6,
|
||||
"outputs": [
|
||||
{
|
||||
"output_type": "stream",
|
||||
"name": "stdout",
|
||||
"text": [
|
||||
"\u001b[32m Phase name:__main__\u001b[0m\n",
|
||||
"\u001b[32m PHASE3:__main__\u001b[0m\n",
|
||||
"\u001b[32m PHASE1:__main__\u001b[0m\n",
|
||||
"\u001b[17mStart MMVC SocketIO Server\u001b[0m\n",
|
||||
"\u001b[34m CONFIG:None, MODEL:None\u001b[0m\n",
|
||||
"DEBUG:asyncio:Using selector: EpollSelector\n"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"# プロキシを起動\n",
|
||||
"ウェブサーバへのアクセスをするためのプロキシを起動します。\n",
|
||||
"\n",
|
||||
"表示されたURLをクリックして開くと別タブでアプリが開きます。\n",
|
||||
"\n",
|
||||
"Colabなので、ロードにある程度時間がかかります(30秒くらい)。"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "WhxcFLQEpctq"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"# (5) プロキシを起動\n",
|
||||
"from google.colab.output import eval_js\n",
|
||||
"proxy = eval_js( \"google.colab.kernel.proxyPort(\" + str(PORT) + \")\" )\n",
|
||||
"print(f\"{proxy}trainer/\")"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "nkRjZm95l87C",
|
||||
"colab": {
|
||||
"base_uri": "https://localhost:8080/",
|
||||
"height": 34
|
||||
},
|
||||
"outputId": "bcca9fae-642c-42f6-f3a5-a8bb0789090f"
|
||||
},
|
||||
"execution_count": 7,
|
||||
"outputs": [
|
||||
{
|
||||
"output_type": "stream",
|
||||
"name": "stdout",
|
||||
"text": [
|
||||
"https://vljlzcgk39q-496ff2e9c6d22116-17357-colab.googleusercontent.com/trainer/\n"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [],
|
||||
"metadata": {
|
||||
"id": "s1aWiBg-cTle"
|
||||
},
|
||||
"execution_count": null,
|
||||
"outputs": []
|
||||
}
|
||||
]
|
||||
}
|
206
README.md
@ -1,132 +1,148 @@
|
||||
VC Helper
|
||||
----
|
||||
[日本語](/README.md) /
|
||||
[英語](/docs_i18n/README_en.md) /
|
||||
[韓国語](/docs_i18n/README_ko.md)/
|
||||
[中国語](/docs_i18n/README_zh.md)/
|
||||
[ドイツ語](/docs_i18n/README_de.md)/
|
||||
[アラビア語](/docs_i18n/README_ar.md)/
|
||||
[ギリシャ語](/docs_i18n/README_el.md)/
|
||||
[スペイン語](/docs_i18n/README_es.md)/
|
||||
[フランス語](/docs_i18n/README_fr.md)/
|
||||
[イタリア語](/docs_i18n/README_it.md)/
|
||||
[ラテン語](/docs_i18n/README_la.md)/
|
||||
[マレー語](/docs_i18n/README_ms.md)/
|
||||
[ロシア語](/docs_i18n/README_ru.md)
|
||||
*日本語以外は機械翻訳です。
|
||||
|
||||
# 概要
|
||||
AIを使ったリアルタイムボイスチェンジャー[MMVC](https://github.com/isletennos/MMVC_Trainer)のヘルパーアプリケーションです。
|
||||
## VCClient
|
||||
|
||||
VCClientは、AIを用いてリアルタイム音声変換を行うソフトウェアです。
|
||||
|
||||
MMVCで必要となる一連の作業(トレーニング用の音声の録音、トレーニング、ボイスチェンジャ)の中で、音声の録音とボイスチェンジャを各種プラットフォームでお手軽に実行できます。
|
||||
## What's New!
|
||||
* v.2.0.78-beta
|
||||
* bugfix: RVCモデルのアップロードエラーを回避
|
||||
* ver.1.x との同時起動ができるようになりました。
|
||||
* 選択できるchunk sizeを増やしました。
|
||||
|
||||
※ トレーニングについては[公式ノートブック](https://github.com/isletennos/MMVC_Trainer)をご利用ください。
|
||||
* v.2.0.77-beta (only for RTX 5090, experimental)
|
||||
* 関連モジュールを5090対応 (開発者がRTX5090未所持のため、動作未検証)
|
||||
* v.2.0.76-beta
|
||||
* new feature:
|
||||
* Beatrice: 話者マージの実装
|
||||
* Beatrice: オートピッチシフト
|
||||
* bugfix:
|
||||
* サーバモードのデバイス選択時の不具合対応
|
||||
* v.2.0.73-beta
|
||||
* new feature:
|
||||
* 編集したbeatrice modelのダウンロード
|
||||
* bugfix:
|
||||
* beatrice v2 のpitch, formantが反映されないバグを修正
|
||||
* Applio のembedderを使用しているモデルのONNXができないバグを修正
|
||||
|
||||
[解説動画](https://youtu.be/MOPqnDPqhAU)
|
||||
## ダウンロードと関連リンク
|
||||
|
||||

|
||||
Windows版、 M1 Mac版はhugging faceのリポジトリからダウンロードできます。
|
||||
|
||||
このアプリケーションを用いることで、以下のことを簡単に行うことができます。
|
||||
* [VCClient のリポジトリ](https://huggingface.co/wok000/vcclient000/tree/main)
|
||||
* [Light VCClient for Beatrice v2 のリポジトリ](https://huggingface.co/wok000/light_vcclient_beatrice/tree/main)
|
||||
|
||||
- MMVCトレーニング用の音声録音
|
||||
- MMVCモデルを用いたリアルタイムボイスチェンジャー
|
||||
- リアルタイム話者切り替え
|
||||
- CPU/GPU切り替え
|
||||
*1 Linuxはリポジトリをcloneしてお使いください。
|
||||
|
||||
本アプリケーションのリアルタイムボイスチェンジャーは、サーバ・クライアント構成で動きます。MMVCのサーバを別のPC上で動かすことで、ゲーム実況など他の負荷の高い処理への影響を抑えながら動かすことができます。
|
||||
### 関連リンク
|
||||
|
||||
* [Beatrice V2 トレーニングコードのリポジトリ](https://huggingface.co/fierce-cats/beatrice-trainer)
|
||||
* [Beatrice V2 トレーニングコード Colab版](https://github.com/w-okada/beatrice-trainer-colab)
|
||||
|
||||
### 関連ソフトウェア
|
||||
|
||||
* [リアルタイムボイスチェンジャ VCClient](https://github.com/w-okada/voice-changer)
|
||||
* [読み上げソフトウェア TTSClient](https://github.com/w-okada/ttsclient)
|
||||
* [リアルタイム音声認識ソフトウェア ASRClient](https://github.com/w-okada/asrclient)
|
||||
|
||||
## VC Clientの特徴
|
||||
|
||||
## 多様なAIモデルをサポート
|
||||
|
||||
| AIモデル | v.2 | v.1 | ライセンス |
|
||||
| ------------------------------------------------------------------------------------------------------------ | --------- | -------------------- | ------------------------------------------------------------------------------------------ |
|
||||
| [RVC ](https://github.com/RVC-Project/Retrieval-based-Voice-Conversion-WebUI/blob/main/docs/jp/README.ja.md) | supported | supported | リポジトリを参照してください。 |
|
||||
| [Beatrice v1](https://prj-beatrice.com/) | n/a | supported (only win) | [独自](https://github.com/w-okada/voice-changer/tree/master/server/voice_changer/Beatrice) |
|
||||
| [Beatrice v2](https://prj-beatrice.com/) | supported | n/a | [独自](https://huggingface.co/wok000/vcclient_model/blob/main/beatrice_v2_beta/readme.md) |
|
||||
| [MMVC](https://github.com/isletennos/MMVC_Trainer) | n/a | supported | リポジトリを参照してください。 |
|
||||
| [so-vits-svc](https://github.com/svc-develop-team/so-vits-svc) | n/a | supported | リポジトリを参照してください。 |
|
||||
| [DDSP-SVC](https://github.com/yxlllc/DDSP-SVC) | n/a | supported | リポジトリを参照してください。 |
|
||||
|
||||
## スタンドアロン、ネットワーク経由の両構成をサポート
|
||||
|
||||
ローカルPCで完結した音声変換も、ネットワークを介した音声変換もサポートしています。
|
||||
ネットワークを介した利用を行うことで、ゲームなどの高負荷なアプリケーションと同時に使用する場合に音声変換の負荷を外部にオフロードすることができます。
|
||||
|
||||

|
||||
|
||||
# 使用方法
|
||||
詳細は[こちら](https://zenn.dev/wok/articles/s01_vc001_top)に纏まっています。
|
||||
## 複数プラットフォームに対応
|
||||
|
||||
# (1) レコーダー(トレーニング用音声録音アプリ)
|
||||
MMVCトレーニング用の音声を簡単に録音できるアプリです。
|
||||
Github Pages上で実行できるため、ブラウザのみあれば様々なプラットフォームからご利用可能です。
|
||||
録音したデータは、ブラウザ上に保存されます。外部に漏れることはありません。
|
||||
Windows, Mac(M1), Linux, Google Colab
|
||||
|
||||
[録音アプリ on Github Pages](https://w-okada.github.io/voice-changer/)
|
||||
*1 Linuxはリポジトリをcloneしてお使いください。
|
||||
|
||||
[解説動画](https://youtu.be/s_GirFEGvaA)
|
||||
## REST APIを提供
|
||||
|
||||
各種プログラミング言語でクライアントを作成することができます。
|
||||
|
||||
詳細については[こちら](https://zenn.dev/wok/articles/s01_vc002_record_voice_for_mmvc)をご確認ください。
|
||||
また、curlなどのOSに組み込まれているHTTPクライアントを使って操作ができます。
|
||||
|
||||
## トラブルシュート
|
||||
|
||||
# (2) プレイヤー(ボイスチェンジャーアプリ)
|
||||
MMVCでボイチェンを行うためのアプリです。
|
||||
[通信編](tutorials/trouble_shoot_communication_ja.md)
|
||||
|
||||
大きく3つの方法でご利用できます。難易度順に次の通りです。
|
||||
- Google Colaboratoryでの利用
|
||||
- 事前ビルド済みのBinaryでの利用
|
||||
- DockerやAnacondaなど環境構築を行った上での利用
|
||||
## 開発者の署名について
|
||||
|
||||
本ソフトウェアやMMVCになじみの薄い方は上から徐々に慣れていくとよいと思います。
|
||||
|
||||
## (2-1) Google Colaboratoryでの利用
|
||||
Googleが提供している機械学習プラットフォームColaboratory上で実行できます。
|
||||
MMVCのモデルをトレーニングが完了している場合、既にColaboratoryを利用していると思いますので、事前準備は必要ありません。ただし、ネットワーク環境やColaboratoryの状況によってボイスチェンジャのタイムラグが大きくなる傾向があります。
|
||||
|
||||
- [超簡単バージョン](https://github.com/w-okada/voice-changer/blob/master/VoiceChangerDemo_Simple.ipynb): 事前設定なしでColabから実行できます。
|
||||
- [普通バージョン](https://github.com/w-okada/voice-changer/blob/master/VoiceChangerDemo.ipynb): Google Driveと連携してモデルを読み込むことができます。
|
||||
|
||||
[解説動画](https://youtu.be/TogfMzXH1T0)
|
||||
|
||||
## (2-2) 事前ビルド済みのBinaryでの利用
|
||||
実行形式のバイナリをダウンロードして実行することができます。
|
||||
Windows版とMac版を提供しています。事前準備は必要ありません。
|
||||
|
||||
・Mac版はダウンロードファイルを解凍したのちに、MMVCServerSIOをダブルクリックしてください。開発元を検証できない旨が示される場合は、再度コントロールキーを押してクリックして実行してください。(詳細下記 *1)
|
||||
|
||||
・Windows版は、directML版とGPU版を提供しています。環境に応じたzipファイルをダウンロードしてください。ダンロードしたzipファイルを解凍して、MMVCServerSIO.exeを実行してください。
|
||||
|
||||
・NvidiaのGPUをお持ちの方はonnxgpuがファイル名に含まれるファイルをご利用ください。多くの場合はonnxgpu_nocudaの方で動きます。環境によって極まれにgpuが認識されない場合があります。その場合はonnxgpu_cudaの方をご利用ください。(サイズが大きく違います。)
|
||||
|
||||
・NvidiaのGPUをお持ちでない方はonnxdirectMLが含まれるファイルをご利用ください。多くの場合は、onnxdirectML_nocudaの方で動きます。環境によって極まれにgpuが認識されない場合があります。その場合はonnxgpu_cudaの方をご利用ください。(サイズが大きく違います。)
|
||||
|
||||
・リモートからアクセスできるようにする方法など、より詳しくは[こちら](https://zenn.dev/wok/articles/s01_vc001_top)をご覧ください。
|
||||
|
||||
|
||||
### 最新バージョン
|
||||
- [MMVCServerSIO_mac_onnxcpu_v.1.3.7.2.zip](https://drive.google.com/file/d/1AcJaQXH8ZtlCSrifvRBWdat19HD_A2fr/view?usp=sharing) 365MB
|
||||
- [MMVCServerSIO_win_onnxdirectML_cuda_v.1.3.7.2.zip](https://drive.google.com/file/d/1WKW3uqmIi9D13Jzao8jWVqx2KANmmQji/view?usp=sharing) 2050MB
|
||||
- [MMVCServerSIO_win_onnxdirectML_nocuda_v.1.3.7.2.zip](https://drive.google.com/file/d/1b8Lqwb7emvd85NwRANPglKWzceJYcgBg/view?usp=sharing) 286MB
|
||||
- [MMVCServerSIO_win_onnxgpu_cuda_v.1.3.7.2.zip](https://drive.google.com/file/d/1XcEslgeyo_SsjeFozyWl0zc4izFVGXHE/view?usp=sharing) 2144MB
|
||||
- [MMVCServerSIO_win_onnxgpu_nocuda_v.1.3.7.2.zip](https://drive.google.com/file/d/1ST7g6jCNm_xe_Q6bj_O-50RMFTDNt_u0/view?usp=sharing) 380MB
|
||||
|
||||
|
||||
### 過去バージョン
|
||||
- [MMVCServerSIO_mac_onnxcpu_v.1.3.7.0.zip](https://drive.google.com/file/d/1K_ihZ8hxbQq10qrxM1WUfUaj_vY6zwrW/view?usp=sharing) 154MB
|
||||
- [MMVCServerSIO_win_onnxdirectML_cuda_v.1.3.7.0.zip](https://drive.google.com/file/d/1IJHazaV60ophM6fbmzugZEjulLpBVJUi/view?usp=sharing) 1962MB
|
||||
- [MMVCServerSIO_win_onnxdirectML_nocuda_v.1.3.7.0.zip](https://drive.google.com/file/d/1_VzdUpiWb8lbIKNppwsFM5pYCAnixOap/view?usp=sharing) 198MB
|
||||
- [MMVCServerSIO_win_onnxgpu_cuda_v.1.3.7.0.zip](https://drive.google.com/file/d/1uRZHnDq2nVx4oRlXXiqZeE-ZjJlAFx5C/view?usp=sharing) 2057MB
|
||||
- [MMVCServerSIO_win_onnxgpu_nocuda_v.1.3.7.0.zip](https://drive.google.com/file/d/1DjSCsc_jKaH-TY6qqFbXz7Ya6tS58odb/view?usp=sharing) 293MB
|
||||
|
||||
|
||||
https://user-images.githubusercontent.com/48346627/212569645-e30b7f4e-079d-4504-8cf8-7816c5f40b00.mp4
|
||||
|
||||
|
||||
詳細は、こちらの[Blog](https://zenn.dev/wok/articles/s01_vc001_top)をご確認ください。
|
||||
|
||||
|
||||
*1 本ソフトウェアは開発元の署名しておりません。下記のように警告が出ますが、コントロールキーを押しながらアイコンをクリックすると実行できるようになります。これはAppleのセキュリティポリシーによるものです。実行は自己責任となります。
|
||||
本ソフトウェアは開発元の署名しておりません。下記のように警告が出ますが、コントロールキーを押しながらアイコンをクリックすると実行できるようになります。これは Apple のセキュリティポリシーによるものです。実行は自己責任となります。
|
||||
|
||||

|
||||
|
||||
## Acknowledgments
|
||||
|
||||
## (2-3) DockerやAnacondaなど環境構築を行った上での利用
|
||||
本リポジトリをクローンして利用します。WindowsではWSL2の環境構築が必須になります。また、WSL2上でDockerもしくはAnacondaなどの仮想環境の構築が必要となります。MacではAnacondaなどのPythonの仮想環境の構築が必要となります。事前準備が必要となりますが、多くの環境においてこの方法が一番高速で動きます。**<font color="red"> GPUが無くてもそこそこ新しいCPUであれば十分動く可能性があります </font>(下記のリアルタイム性の節を参照)**。
|
||||
* [立ちずんだもん素材](https://seiga.nicovideo.jp/seiga/im10792934)
|
||||
* [いらすとや](https://www.irasutoya.com/)
|
||||
* [つくよみちゃん](https://tyc.rei-yumesaki.net/)
|
||||
|
||||
[WSL2とDockerのインストールの解説動画](https://youtu.be/POo_Cg0eFMU)
|
||||
```
|
||||
本ソフトウェアの音声合成には、フリー素材キャラクター「つくよみちゃん」が無料公開している音声データを使用しています。
|
||||
■つくよみちゃんコーパス(CV.夢前黎)
|
||||
https://tyc.rei-yumesaki.net/material/corpus/
|
||||
© Rei Yumesaki
|
||||
```
|
||||
|
||||
[WSL2とAnacondaのインストールの解説動画](https://youtu.be/fba9Zhsukqw)
|
||||
* [あみたろの声素材工房](https://amitaro.net/)
|
||||
* [れぷりかどーる](https://kikyohiroto1227.wixsite.com/kikoto-utau)
|
||||
|
||||
操作方法は[こちら](https://zenn.dev/wok/articles/s01_vc007_mmvc_with_linux_wsl2)をご覧ください。
|
||||
## 利用規約
|
||||
|
||||
## リアルタイム性
|
||||
* リアルタイムボイスチェンジャーつくよみちゃんについては、つくよみちゃんコーパスの利用規約に準じ、次の目的で変換後の音声を使用することを禁止します。
|
||||
|
||||
GPUを使用するとほとんどタイムラグなく変換可能です。
|
||||
```
|
||||
|
||||
https://twitter.com/DannadoriYellow/status/1613483372579545088?s=20&t=7CLD79h1F3dfKiTb7M8RUQ
|
||||
■人を批判・攻撃すること。(「批判・攻撃」の定義は、つくよみちゃんキャラクターライセンスに準じます)
|
||||
|
||||
CPUでも最近のであればそれなりの速度で変換可能。
|
||||
■特定の政治的立場・宗教・思想への賛同または反対を呼びかけること。
|
||||
|
||||
https://twitter.com/DannadoriYellow/status/1613553862773997569?s=20&t=7CLD79h1F3dfKiTb7M8RUQ
|
||||
■刺激の強い表現をゾーニングなしで公開すること。
|
||||
|
||||
古いCPU( i7-4770)だと、1000msecくらいかかってしまう。
|
||||
■他者に対して二次利用(素材としての利用)を許可する形で公開すること。
|
||||
※鑑賞用の作品として配布・販売していただくことは問題ございません。
|
||||
```
|
||||
|
||||
# Acknowledgments
|
||||
- 立ちずんだもん素材:https://seiga.nicovideo.jp/seiga/im10792934
|
||||
- いらすとや:https://www.irasutoya.com/
|
||||
* リアルタイムボイスチェンジャーあみたろについては、あみたろの声素材工房様の次の利用規約に準じます。詳細は[こちら](https://amitaro.net/voice/faq/#index_id6)
|
||||
|
||||
```
|
||||
あみたろの声素材やコーパス読み上げ音声を使って音声モデルを作ったり、ボイスチェンジャーや声質変換などを使用して、自分の声をあみたろの声に変換して使うのもOKです。
|
||||
|
||||
ただしその場合は絶対に、あみたろ(もしくは小春音アミ)の声に声質変換していることを明記し、あみたろ(および小春音アミ)が話しているわけではないことが誰でもわかるようにしてください。
|
||||
また、あみたろの声で話す内容は声素材の利用規約の範囲内のみとし、センシティブな発言などはしないでください。
|
||||
```
|
||||
|
||||
* リアルタイムボイスチェンジャー黄琴まひろについては、れぷりかどーるの利用規約に準じます。詳細は[こちら](https://kikyohiroto1227.wixsite.com/kikoto-utau/ter%EF%BD%8Ds-of-service)
|
||||
|
||||
## 免責事項
|
||||
|
||||
# 免責事項
|
||||
本ソフトウェアの使用または使用不能により生じたいかなる直接損害・間接損害・波及的損害・結果的損害 または特別損害についても、一切責任を負いません。
|
||||
|
||||
|
||||
|
122
README_dev_en.md
Normal file
@ -0,0 +1,122 @@
|
||||
## For Developper
|
||||
|
||||
[Japanese](/README_dev_ja.md) [Russian](/README_dev_ru.md)
|
||||
|
||||
## Prerequisit
|
||||
|
||||
- Linux(ubuntu, debian) or WSL2, (not tested for other linux distributions and Mac)
|
||||
- Anaconda
|
||||
|
||||
## Preparation
|
||||
|
||||
1. Create anaconda virtual environment
|
||||
|
||||
```
|
||||
$ conda create -n vcclient-dev python=3.10
|
||||
$ conda activate vcclient-dev
|
||||
```
|
||||
|
||||
2. clone repository
|
||||
|
||||
```
|
||||
$ git clone https://github.com/w-okada/voice-changer.git
|
||||
```
|
||||
|
||||
## For Server Developer
|
||||
|
||||
1. Install requirements
|
||||
|
||||
```
|
||||
$ cd voice-changer/server
|
||||
$ pip install -r requirements.txt
|
||||
```
|
||||
|
||||
2. Run server
|
||||
|
||||
Run server with the below command. You can replace the path to each weight.
|
||||
|
||||
```
|
||||
$ python3 MMVCServerSIO.py -p 18888 --https true \
|
||||
--content_vec_500 pretrain/checkpoint_best_legacy_500.pt \
|
||||
--content_vec_500_onnx pretrain/content_vec_500.onnx \
|
||||
--content_vec_500_onnx_on true \
|
||||
--hubert_base pretrain/hubert_base.pt \
|
||||
--hubert_base_jp pretrain/rinna_hubert_base_jp.pt \
|
||||
--hubert_soft pretrain/hubert/hubert-soft-0d54a1f4.pt \
|
||||
--nsf_hifigan pretrain/nsf_hifigan/model \
|
||||
--crepe_onnx_full pretrain/crepe_onnx_full.onnx \
|
||||
--crepe_onnx_tiny pretrain/crepe_onnx_tiny.onnx \
|
||||
--rmvpe pretrain/rmvpe.pt \
|
||||
--model_dir model_dir \
|
||||
--samples samples.json
|
||||
|
||||
```
|
||||
|
||||
Access with Browser (currently only chrome is supported), then you can see gui.
|
||||
|
||||
2-1. Trouble shoot
|
||||
|
||||
(1) OSError: PortAudio library not found
|
||||
If you get the message below, you shold install additional library.
|
||||
|
||||
```
|
||||
OSError: PortAudio library not found
|
||||
```
|
||||
|
||||
You can install the library this command.
|
||||
|
||||
```
|
||||
$ sudo apt-get install libportaudio2
|
||||
$ sudo apt-get install libasound-dev
|
||||
```
|
||||
|
||||
(2) It's not starting up! Damn software!
|
||||
|
||||
The client will not start automatically. Please launch your browser and access the URL displayed on the console. And watch your words.
|
||||
|
||||
(3) Could not load library libcudnn_cnn_infer.so.8
|
||||
|
||||
When using WSL, you might encounter a message saying `Could not load library libcudnn_cnn_infer.so.8. Error: libcuda.so: cannot open shared object file: No such file or directory`. This often happens because the path hasn't been properly set. Please set the path as shown below. It might be handy to add this to your launch script, such as .bashrc.
|
||||
|
||||
```
|
||||
export LD_LIBRARY_PATH=/usr/lib/wsl/lib:$LD_LIBRARY_PATH
|
||||
```
|
||||
|
||||
- reference
|
||||
- https://qiita.com/cacaoMath/items/811146342946cdde5b83
|
||||
- https://github.com/microsoft/WSL/issues/8587
|
||||
|
||||
3. Enjoy developing.
|
||||
|
||||
### Appendix
|
||||
|
||||
1. Win + Anaconda (not supported)
|
||||
|
||||
use conda to install pytorch
|
||||
|
||||
```
|
||||
conda install pytorch torchvision torchaudio pytorch-cuda=11.8 -c pytorch -c nvidia
|
||||
```
|
||||
|
||||
Also run these command.
|
||||
|
||||
```
|
||||
pip install chardet
|
||||
pip install numpy==1.24.0
|
||||
```
|
||||
|
||||
## For Client Developer
|
||||
|
||||
1. Import modules and initial build
|
||||
|
||||
```
|
||||
cd client
|
||||
cd lib
|
||||
npm install
|
||||
npm run build:dev
|
||||
cd ../demo
|
||||
npm install
|
||||
npm run build:dev
|
||||
```
|
||||
|
||||
2. Enjoy developing.
|
122
README_dev_ja.md
Normal file
@ -0,0 +1,122 @@
|
||||
## 開発者向け
|
||||
|
||||
[English](/README_dev_en.md)
|
||||
|
||||
## 前提
|
||||
|
||||
- Linux(ubuntu, debian) or WSL2, (not tested for other linux distributions and Mac)
|
||||
- Anaconda
|
||||
|
||||
## 準備
|
||||
|
||||
1. Anaconda の仮想環境を作成する
|
||||
|
||||
```
|
||||
$ conda create -n vcclient-dev python=3.10
|
||||
$ conda activate vcclient-dev
|
||||
```
|
||||
|
||||
2. リポジトリをクローンする
|
||||
|
||||
```
|
||||
$ git clone https://github.com/w-okada/voice-changer.git
|
||||
```
|
||||
|
||||
## サーバ開発者向け
|
||||
|
||||
1. モジュールをインストールする
|
||||
|
||||
```
|
||||
$ cd voice-changer/server
|
||||
$ pip install -r requirements.txt
|
||||
```
|
||||
|
||||
2. サーバを起動する
|
||||
|
||||
次のコマンドで起動します。各種重みについてのパスは環境に合わせて変えてください。
|
||||
|
||||
```
|
||||
$ python3 MMVCServerSIO.py -p 18888 --https true \
|
||||
--content_vec_500 pretrain/checkpoint_best_legacy_500.pt \
|
||||
--content_vec_500_onnx pretrain/content_vec_500.onnx \
|
||||
--content_vec_500_onnx_on true \
|
||||
--hubert_base pretrain/hubert_base.pt \
|
||||
--hubert_base_jp pretrain/rinna_hubert_base_jp.pt \
|
||||
--hubert_soft pretrain/hubert/hubert-soft-0d54a1f4.pt \
|
||||
--nsf_hifigan pretrain/nsf_hifigan/model \
|
||||
--crepe_onnx_full pretrain/crepe_onnx_full.onnx \
|
||||
--crepe_onnx_tiny pretrain/crepe_onnx_tiny.onnx \
|
||||
--rmvpe pretrain/rmvpe.pt \
|
||||
--model_dir model_dir \
|
||||
--samples samples.json
|
||||
```
|
||||
|
||||
ブラウザ(Chrome のみサポート)でアクセスすると画面が表示されます。
|
||||
|
||||
2-1. トラブルシュート
|
||||
|
||||
(1) OSError: PortAudio library not found
|
||||
次のようなメッセージが表示される場合、追加でライブラリを追加する必要があります。
|
||||
|
||||
```
|
||||
OSError: PortAudio library not found
|
||||
```
|
||||
|
||||
ubuntu(wsl2)の場合下記のコマンドでインストールできます。
|
||||
|
||||
```
|
||||
$ sudo apt-get install libportaudio2
|
||||
$ sudo apt-get install libasound-dev
|
||||
```
|
||||
|
||||
(2) 起動しないんだけど!?
|
||||
|
||||
自動でクライアントは起動しません。ブラウザを立ち上げてコンソールに表示された URL にアクセスしてください。
|
||||
|
||||
(3) Could not load library libcudnn_cnn_infer.so.8
|
||||
WSL を使っていると`Could not load library libcudnn_cnn_infer.so.8. Error: libcuda.so: cannot open shared object file: No such file or directory`と表示される場合があります。
|
||||
パスが通っていないことが原因のことが多いです。下記のようにパスを通して実行してください。
|
||||
.bashrc など起動スクリプトに追加しておくと便利だと思います。
|
||||
|
||||
```
|
||||
export LD_LIBRARY_PATH=/usr/lib/wsl/lib:$LD_LIBRARY_PATH
|
||||
```
|
||||
|
||||
- 参考
|
||||
- https://qiita.com/cacaoMath/items/811146342946cdde5b83
|
||||
- https://github.com/microsoft/WSL/issues/8587
|
||||
|
||||
3. 開発しましょう
|
||||
|
||||
### Appendix
|
||||
|
||||
1. Win + Anaconda のとき (not supported)
|
||||
|
||||
pytorch を conda で入れないと gpu を認識しないかもしれない。
|
||||
|
||||
```
|
||||
conda install pytorch torchvision torchaudio pytorch-cuda=11.8 -c pytorch -c nvidia
|
||||
```
|
||||
|
||||
また、追加で下記も必要のようだ。
|
||||
|
||||
```
|
||||
pip install chardet
|
||||
pip install numpy==1.24.0
|
||||
```
|
||||
|
||||
## クライアント開発者向け
|
||||
|
||||
1. モジュールをインストールして、一度ビルドします
|
||||
|
||||
```
|
||||
cd client
|
||||
cd lib
|
||||
npm install
|
||||
npm run build:dev
|
||||
cd ../demo
|
||||
npm install
|
||||
npm run build:dev
|
||||
```
|
||||
|
||||
2. 開発しましょう
|
122
README_dev_ko.md
Normal file
@ -0,0 +1,122 @@
|
||||
## 개발자용
|
||||
|
||||
[English](/README_dev_en.md) [Korean](/README_dev_ko.md)
|
||||
|
||||
## 전제
|
||||
|
||||
- Linux(ubuntu, debian) or WSL2, (다른 리눅스 배포판과 Mac에서는 테스트하지 않았습니다)
|
||||
- Anaconda
|
||||
|
||||
## 준비
|
||||
|
||||
1. Anaconda 가상 환경을 작성한다
|
||||
|
||||
```
|
||||
$ conda create -n vcclient-dev python=3.10
|
||||
$ conda activate vcclient-dev
|
||||
```
|
||||
|
||||
2. 리포지토리를 클론한다
|
||||
|
||||
```
|
||||
$ git clone https://github.com/w-okada/voice-changer.git
|
||||
```
|
||||
|
||||
## 서버 개발자용
|
||||
|
||||
1. 모듈을 설치한다
|
||||
|
||||
```
|
||||
$ cd voice-changer/server
|
||||
$ pip install -r requirements.txt
|
||||
```
|
||||
|
||||
2. 서버를 구동한다
|
||||
|
||||
다음 명령어로 구동합니다. 여러 가중치에 대한 경로는 환경에 맞게 변경하세요.
|
||||
|
||||
```
|
||||
$ python3 MMVCServerSIO.py -p 18888 --https true \
|
||||
--content_vec_500 pretrain/checkpoint_best_legacy_500.pt \
|
||||
--content_vec_500_onnx pretrain/content_vec_500.onnx \
|
||||
--content_vec_500_onnx_on true \
|
||||
--hubert_base pretrain/hubert_base.pt \
|
||||
--hubert_base_jp pretrain/rinna_hubert_base_jp.pt \
|
||||
--hubert_soft pretrain/hubert/hubert-soft-0d54a1f4.pt \
|
||||
--nsf_hifigan pretrain/nsf_hifigan/model \
|
||||
--crepe_onnx_full pretrain/crepe_onnx_full.onnx \
|
||||
--crepe_onnx_tiny pretrain/crepe_onnx_tiny.onnx \
|
||||
--rmvpe pretrain/rmvpe.pt \
|
||||
--model_dir model_dir \
|
||||
--samples samples.json
|
||||
```
|
||||
|
||||
브라우저(Chrome에서만 지원)에서 접속하면 화면이 나옵니다.
|
||||
|
||||
2-1. 문제 해결법
|
||||
|
||||
(1) OSError: PortAudio library not found
|
||||
다음과 같은 메시지가 나올 경우에는 추가 라이브러리를 설치해야 합니다.
|
||||
|
||||
```
|
||||
OSError: PortAudio library not found
|
||||
```
|
||||
|
||||
ubuntu(wsl2)인 경우에는 아래 명령어로 설치할 수 있습니다.
|
||||
|
||||
```
|
||||
$ sudo apt-get install libportaudio2
|
||||
$ sudo apt-get install libasound-dev
|
||||
```
|
||||
|
||||
(2) 서버 구동이 안 되는데요?!
|
||||
|
||||
클라이언트는 자동으로 구동되지 않습니다. 브라우저를 실행하고 콘솔에 표시된 URL로 접속하세요.
|
||||
|
||||
(3) Could not load library libcudnn_cnn_infer.so.8
|
||||
WSL를 사용 중이라면 `Could not load library libcudnn_cnn_infer.so.8. Error: libcuda.so: cannot open shared object file: No such file or directory`라는 메시지가 나오는 경우가 있습니다.
|
||||
잘못된 경로가 원인인 경우가 많습니다. 아래와 같이 경로를 바꾸고 실행해 보세요.
|
||||
.bashrc 등 구동 스크립트에 추가해 두면 편리합니다.
|
||||
|
||||
```
|
||||
export LD_LIBRARY_PATH=/usr/lib/wsl/lib:$LD_LIBRARY_PATH
|
||||
```
|
||||
|
||||
- 참고
|
||||
- https://qiita.com/cacaoMath/items/811146342946cdde5b83
|
||||
- https://github.com/microsoft/WSL/issues/8587
|
||||
|
||||
3. 개발하세요
|
||||
|
||||
### Appendix
|
||||
|
||||
1. Win + Anaconda일 때 (not supported)
|
||||
|
||||
pytorch를 conda가 없으면 gpu를 인식하지 않을 수 있습니다.
|
||||
|
||||
```
|
||||
conda install pytorch torchvision torchaudio pytorch-cuda=11.8 -c pytorch -c nvidia
|
||||
```
|
||||
|
||||
또한 추가로 아래 내용도 필요합니다.
|
||||
|
||||
```
|
||||
pip install chardet
|
||||
pip install numpy==1.24.0
|
||||
```
|
||||
|
||||
## 클라이언트 개발자용
|
||||
|
||||
1. 모듈을 설치하고 한번 빌드합니다
|
||||
|
||||
```
|
||||
cd client
|
||||
cd lib
|
||||
npm install
|
||||
npm run build:dev
|
||||
cd ../demo
|
||||
npm install
|
||||
npm run build:dev
|
||||
```
|
||||
|
||||
2. 개발하세요
|
124
README_dev_ru.md
Normal file
@ -0,0 +1,124 @@
|
||||
Вот перевод файла `README_dev_en.md` на русский язык:
|
||||
|
||||
## Для разработчиков
|
||||
|
||||
[Японский](/README_dev_ja.md) [Английский](/README_dev_en.md)
|
||||
|
||||
## Требования
|
||||
|
||||
- Linux (Ubuntu, Debian) или WSL2 (другие дистрибуции Linux и Mac не тестировались)
|
||||
- Anaconda
|
||||
|
||||
## Подготовка
|
||||
|
||||
1. Создайте виртуальную среду Anaconda:
|
||||
|
||||
```
|
||||
$ conda create -n vcclient-dev python=3.10
|
||||
$ conda activate vcclient-dev
|
||||
```
|
||||
|
||||
2. Клонируйте репозиторий:
|
||||
|
||||
```
|
||||
$ git clone https://github.com/w-okada/voice-changer.git
|
||||
```
|
||||
|
||||
## Для серверных разработчиков
|
||||
|
||||
1. Установите необходимые зависимости:
|
||||
|
||||
```
|
||||
$ cd voice-changer/server
|
||||
$ pip install -r requirements.txt
|
||||
```
|
||||
|
||||
2. Запустите сервер
|
||||
|
||||
Запустите сервер с помощью следующей команды. Вы можете указать свои пути к весам моделей.
|
||||
|
||||
```
|
||||
$ python3 MMVCServerSIO.py -p 18888 --https true \
|
||||
--content_vec_500 pretrain/checkpoint_best_legacy_500.pt \
|
||||
--content_vec_500_onnx pretrain/content_vec_500.onnx \
|
||||
--content_vec_500_onnx_on true \
|
||||
--hubert_base pretrain/hubert_base.pt \
|
||||
--hubert_base_jp pretrain/rinna_hubert_base_jp.pt \
|
||||
--hubert_soft pretrain/hubert/hubert-soft-0d54a1f4.pt \
|
||||
--nsf_hifigan pretrain/nsf_hifigan/model \
|
||||
--crepe_onnx_full pretrain/crepe_onnx_full.onnx \
|
||||
--crepe_onnx_tiny pretrain/crepe_onnx_tiny.onnx \
|
||||
--rmvpe pretrain/rmvpe.pt \
|
||||
--model_dir model_dir \
|
||||
--samples samples.json
|
||||
```
|
||||
|
||||
Откройте браузер (на данный момент поддерживается только Chrome), и вы увидите графический интерфейс.
|
||||
|
||||
2-1. Устранение неполадок
|
||||
|
||||
(1) OSError: не найдена библиотека PortAudio
|
||||
|
||||
Если вы получите сообщение ниже, необходимо установить дополнительную библиотеку:
|
||||
|
||||
```
|
||||
OSError: PortAudio library not found
|
||||
```
|
||||
|
||||
Вы можете установить библиотеку командой:
|
||||
|
||||
```
|
||||
$ sudo apt-get install libportaudio2
|
||||
$ sudo apt-get install libasound-dev
|
||||
```
|
||||
|
||||
(2) Не запускается! Чертова программа!
|
||||
|
||||
Клиент не запускается автоматически. Пожалуйста, откройте браузер и перейдите по URL, отображаемому в консоли. И будьте осторожны со словами.
|
||||
|
||||
(3) Не удалось загрузить библиотеку libcudnn_cnn_infer.so.8
|
||||
|
||||
При использовании WSL может возникнуть ошибка `Could not load library libcudnn_cnn_infer.so.8. Error: libcuda.so: cannot open shared object file: No such file or directory`. Это часто связано с тем, что путь к библиотеке не установлен. Установите путь с помощью команды ниже. Вы можете добавить эту команду в ваш скрипт запуска, например, в .bashrc.
|
||||
|
||||
```
|
||||
export LD_LIBRARY_PATH=/usr/lib/wsl/lib:$LD_LIBRARY_PATH
|
||||
```
|
||||
|
||||
- ссылки:
|
||||
- https://qiita.com/cacaoMath/items/811146342946cdde5b83
|
||||
- https://github.com/microsoft/WSL/issues/8587
|
||||
|
||||
3. Наслаждайтесь разработкой.
|
||||
|
||||
### Приложение
|
||||
|
||||
1. Windows + Anaconda (не поддерживается)
|
||||
|
||||
Используйте conda для установки PyTorch:
|
||||
|
||||
```
|
||||
conda install pytorch torchvision torchaudio pytorch-cuda=11.8 -c pytorch -c nvidia
|
||||
```
|
||||
|
||||
Также выполните эти команды:
|
||||
|
||||
```
|
||||
pip install chardet
|
||||
pip install numpy==1.24.0
|
||||
```
|
||||
|
||||
## Для клиентских разработчиков
|
||||
|
||||
1. Импорт модулей и начальная сборка:
|
||||
|
||||
```
|
||||
cd client
|
||||
cd lib
|
||||
npm install
|
||||
npm run build:dev
|
||||
cd ../demo
|
||||
npm install
|
||||
npm run build:dev
|
||||
```
|
||||
|
||||
2. Наслаждайтесь.
|
151
README_en.md
Normal file
@ -0,0 +1,151 @@
|
||||
## VC Client
|
||||
|
||||
[Japanese](/README_ja.md) [Korean](/README_ko.md) [Russian](/README_ru.md)
|
||||
|
||||
## What's New!
|
||||
- We have released a sister product, the Text To Speech client.
|
||||
- You can enjoy voice generation with a simple interface.
|
||||
- For more details, click [here](https://github.com/w-okada/ttsclient).
|
||||
- Beatrice V2 Training Code Released!!!
|
||||
- [Training Code Repository](https://huggingface.co/fierce-cats/beatrice-trainer)
|
||||
- [Colab Version](https://github.com/w-okada/beatrice-trainer-colab)
|
||||
- v.2.0.70-beta (only for m1 mac)
|
||||
- [HERE](https://github.com/w-okada/voice-changer/tree/v.2)
|
||||
- new feature:
|
||||
- The M1 Mac version of VCClient now supports Beatrice v2 beta.1.
|
||||
- v.2.0.69-beta (only for win)
|
||||
- [HERE](https://github.com/w-okada/voice-changer/tree/v.2)
|
||||
- bugfix:
|
||||
- Fixed a bug where the start button would not be displayed in case of some exceptions
|
||||
- Adjusted the output buffer for server device mode
|
||||
- Fixed a bug where the sampling rate would change when settings were modified while using server device mode
|
||||
- Fixed a bug when using Japanese hubert
|
||||
- misc:
|
||||
- Added host API filter (highlighted) for server device mode
|
||||
- v.2.0.65-beta
|
||||
- [HERE](https://github.com/w-okada/voice-changer/tree/v.2)
|
||||
- new feature: We have supported Beatrice v2 beta.1, enabling even higher quality voice conversion.
|
||||
|
||||
# What is VC Client
|
||||
|
||||
1. This is a client software for performing real-time voice conversion using various Voice Conversion (VC) AI. The supported AI for voice conversion are as follows.
|
||||
|
||||
- [MMVC](https://github.com/isletennos/MMVC_Trainer) (only v1)
|
||||
- [so-vits-svc](https://github.com/svc-develop-team/so-vits-svc) (only v1)
|
||||
- [RVC(Retrieval-based-Voice-Conversion)](https://github.com/liujing04/Retrieval-based-Voice-Conversion-WebUI)
|
||||
- [DDSP-SVC](https://github.com/yxlllc/DDSP-SVC) (only v1)
|
||||
- [Beatrice JVS Corpus Edition](https://prj-beatrice.com/) * experimental, (***NOT MIT License*** see [readme](https://github.com/w-okada/voice-changer/blob/master/server/voice_changer/Beatrice/)) * Only for Windows, CPU dependent (only v1)
|
||||
- [Beatrice v2](https://prj-beatrice.com/) (only for v2)
|
||||
|
||||
1. Distribute the load by running Voice Changer on a different PC
|
||||
The real-time voice changer of this application works on a server-client configuration. By running the MMVC server on a separate PC, you can run it while minimizing the impact on other resource-intensive processes such as gaming commentary.
|
||||
|
||||

|
||||
|
||||
3. Cross-platform compatibility
|
||||
Supports Windows, Mac (including Apple Silicon M1), Linux, and Google Colaboratory.
|
||||
## Related Software
|
||||
- [Real-time Voice Changer VCClient](https://github.com/w-okada/voice-changer)
|
||||
- [Text-to-Speech Software TTSClient](https://github.com/w-okada/ttsclient)
|
||||
- [Real-Time Speech Recognition Software ASRClient](https://github.com/w-okada/asrclient)
|
||||
# usage
|
||||
|
||||
This is an app for performing voice changes with MMVC and so-vits-svc.
|
||||
|
||||
It can be used in two main ways, in order of difficulty:
|
||||
|
||||
- Using a pre-built binary
|
||||
- Setting up an environment with Docker or Anaconda and using it
|
||||
|
||||
## (1) Usage with pre-built binaries
|
||||
|
||||
- You can download and run executable binaries.
|
||||
|
||||
- Please see [here](tutorials/tutorial_rvc_en_latest.md) for the tutorial. ([trouble shoot](https://github.com/w-okada/voice-changer/blob/master/tutorials/trouble_shoot_communication_ja.md))
|
||||
|
||||
- It's now easy to try it out on [Google Colaboratory](https://github.com/w-okada/voice-changer/tree/v.2/w_okada's_Voice_Changer_version_2_x.ipynb) (requires a ngrok account). You can launch it from the 'Open in Colab' button in the top left corner.
|
||||
|
||||
<img src="https://github.com/w-okada/voice-changer/assets/48346627/3f092e2d-6834-42f6-bbfd-7d389111604e" width="400" height="150">
|
||||
|
||||
- We offer Windows and Mac versions on [hugging face](https://huggingface.co/wok000/vcclient000/tree/main)
|
||||
- v2 for Windows
|
||||
- Please download and use `vcclient_win_std_xxx.zip`. You can perform voice conversion using a reasonably high-performance CPU without a GPU, or by utilizing DirectML to leverage GPUs (AMD, Nvidia). v2 supports both torch and onnx.
|
||||
- If you have an Nvidia GPU, you can achieve faster voice conversion by using `vcclient_win_cuda_xxx.zip`.
|
||||
- v2 for Mac (Apple Silicon)
|
||||
- Please download and use `vcclient_mac_xxx.zip`.
|
||||
- v1
|
||||
- If you are using a Windows and Nvidia GPU, please download ONNX (cpu, cuda), PyTorch (cpu, cuda).
|
||||
- If you are using a Windows and AMD/Intel GPU, please download ONNX (cpu, DirectML) and PyTorch (cpu, cuda). AMD/Intel GPUs are only enabled for ONNX models.
|
||||
- In either case, for GPU support, PyTorch and Onnxruntime are only enabled if supported.
|
||||
- If you are not using a GPU on Windows, please download ONNX (cpu, cuda) and PyTorch (cpu, cuda).
|
||||
|
||||
- For Windows user, after unzipping the downloaded zip file, please run the `start_http.bat` file corresponding to your VC.
|
||||
|
||||
- For Mac version, after unzipping the downloaded file, double-click the `startHttp.command` file corresponding to your VC. If a message indicating that the developer cannot be verified is displayed, please press the control key and click to run it again (or right-click to run it).
|
||||
|
||||
- If you are connecting remotely, please use the `.command` file (Mac) or `.bat` file (Windows) with https instead of http.
|
||||
|
||||
- The encoder of DDPS-SVC only supports hubert-soft.
|
||||
|
||||
- [Download from hugging face](https://huggingface.co/wok000/vcclient000/tree/main)
|
||||
|
||||
## (2) Usage after setting up the environment such as Docker or Anaconda
|
||||
|
||||
Clone this repository and use it. Setting up WSL2 is essential for Windows. Additionally, setting up virtual environments such as Docker or Anaconda on WSL2 is also required. On Mac, setting up Python virtual environments such as Anaconda is necessary. Although preparation is required, this method works the fastest in many environments. **<font color="red"> Even without a GPU, it may work well enough with a reasonably new CPU </font>(refer to the section on real-time performance below)**.
|
||||
|
||||
[Explanation video on installing WSL2 and Docker](https://youtu.be/POo_Cg0eFMU)
|
||||
|
||||
[Explanation video on installing WSL2 and Anaconda](https://youtu.be/fba9Zhsukqw)
|
||||
|
||||
To run docker, see [start docker](docker_vcclient/README_en.md).
|
||||
|
||||
To run on Anaconda venv, see [server developer's guide](README_dev_en.md)
|
||||
|
||||
To run on Linux using an AMD GPU, see [setup guide linux](tutorials/tutorial_anaconda_amd_rocm.md)
|
||||
|
||||
|
||||
# Software Signing
|
||||
|
||||
This software is not signed by the developer. A warning message will appear, but you can run the software by clicking the icon while holding down the control key. This is due to Apple's security policy. Running the software is at your own risk.
|
||||
|
||||

|
||||
|
||||
https://user-images.githubusercontent.com/48346627/212569645-e30b7f4e-079d-4504-8cf8-7816c5f40b00.mp4
|
||||
|
||||
# Acknowledgments
|
||||
|
||||
- [Tachizunda-mon materials](https://seiga.nicovideo.jp/seiga/im10792934)
|
||||
- [Irasutoya](https://www.irasutoya.com/)
|
||||
- [Tsukuyomi-chan](https://tyc.rei-yumesaki.net)
|
||||
|
||||
> This software uses the voice data of the free material character "Tsukuyomi-chan," which is provided for free by CV. Yumesaki Rei.
|
||||
>
|
||||
> - Tsukuyomi-chan Corpus (CV. Yumesaki Rei)
|
||||
>
|
||||
> https://tyc.rei-yumesaki.net/material/corpus/
|
||||
>
|
||||
> Copyright. Rei Yumesaki
|
||||
|
||||
- [Amitaro's Onsozai kobo](https://amitaro.net/)
|
||||
- [Replica doll](https://kikyohiroto1227.wixsite.com/kikoto-utau)
|
||||
|
||||
# Terms of Use
|
||||
|
||||
In accordance with the Tsukuyomi-chan Corpus Terms of Use for the Tsukuyomi-chan Real-time Voice Changer, the use of the converted voice for the following purposes is prohibited.
|
||||
|
||||
- Criticizing or attacking individuals (the definition of "criticizing or attacking" is based on the Tsukuyomi-chan character license).
|
||||
|
||||
- Advocating for or opposing specific political positions, religions, or ideologies.
|
||||
|
||||
- Publicly displaying strongly stimulating expressions without proper zoning.
|
||||
|
||||
- Publicly disclosing secondary use (use as materials) for others.
|
||||
(Distributing or selling as a work for viewing is not a problem.)
|
||||
|
||||
Regarding the Real-time Voice Changer Amitaro, we prohibit the following uses in accordance with the terms of use of the Amitaro's koe-sozai kobo.[detail](https://amitaro.net/voice/faq/#index_id6)
|
||||
|
||||
Regarding the Real-time Voice Changer Kikoto Mahiro, we prohibit the following uses in accordance with the terms of use of Replica doll.[detail](https://kikyohiroto1227.wixsite.com/kikoto-utau/ter%EF%BD%8Ds-of-service)
|
||||
|
||||
# Disclaimer
|
||||
|
||||
We are not liable for any direct, indirect, consequential, incidental, or special damages arising out of or in any way connected with the use or inability to use this software.
|
185
README_ko.md
Normal file
@ -0,0 +1,185 @@
|
||||
## VC Client
|
||||
|
||||
[English](/README_en.md) [Korean](/README_ko.md)
|
||||
|
||||
## 새로운 기능!
|
||||
- 자매품으로 텍스트 음성 변환 클라이언트를 출시하였습니다.
|
||||
- 간단한 인터페이스로 음성 생성을 즐길 수 있습니다.
|
||||
- 자세한 내용은 [여기](https://github.com/w-okada/ttsclient)를 참조하세요.
|
||||
- Beatrice V2 훈련 코드 공개!!!
|
||||
- [훈련 코드 리포지토리](https://huggingface.co/fierce-cats/beatrice-trainer)
|
||||
- [Colab 버전](https://github.com/w-okada/beatrice-trainer-colab)
|
||||
- v.2.0.70-beta (only for m1 mac)
|
||||
- [여기를 참조하십시오](https://github.com/w-okada/voice-changer/tree/v.2)
|
||||
- new feature:
|
||||
- M1 Mac 버전 VCClient에서도 Beatrice v2 beta.1을 지원합니다.
|
||||
- v.2.0.69-beta (only for win)
|
||||
- [여기를 참조하십시오](https://github.com/w-okada/voice-changer/tree/v.2)
|
||||
- 버그 수정:
|
||||
- 일부 예외 발생 시 시작 버튼이 표시되지 않는 버그를 수정
|
||||
- 서버 디바이스 모드의 출력 버퍼 조정
|
||||
- 서버 디바이스 모드 사용 중 설정 변경 시 샘플링 레이트가 변하는 버그 수정
|
||||
- 일본어 hubert 사용 시 버그 수정
|
||||
- 기타:
|
||||
- 서버 디바이스 모드에 호스트 API 필터 추가 (강조 표시)
|
||||
- v.2.0.65-beta
|
||||
- [여기를 참조하십시오](https://github.com/w-okada/voice-changer/tree/v.2)
|
||||
- new feature: Beatrice v2 beta.1를 지원하여 더 높은 품질의 음성 변환이 가능해졌습니다
|
||||
|
||||
# VC Client란
|
||||
|
||||
1. 각종 음성 변환 AI(VC, Voice Conversion)를 활용해 실시간 음성 변환을 하기 위한 클라이언트 소프트웨어입니다. 지원하는 음성 변환 AI는 다음과 같습니다.
|
||||
|
||||
- 지원하는 음성 변환 AI (지원 VC)
|
||||
- [MMVC](https://github.com/isletennos/MMVC_Trainer) (only v1)
|
||||
- [so-vits-svc](https://github.com/svc-develop-team/so-vits-svc) (only v1)
|
||||
- [RVC(Retrieval-based-Voice-Conversion)](https://github.com/liujing04/Retrieval-based-Voice-Conversion-WebUI)
|
||||
- [DDSP-SVC](https://github.com/yxlllc/DDSP-SVC) (only v1)
|
||||
- [Beatrice JVS Corpus Edition](https://prj-beatrice.com/) * experimental, (***NOT MIT License*** see [readme](https://github.com/w-okada/voice-changer/blob/master/server/voice_changer/Beatrice/)) * Only for Windows, CPU dependent (only v1)
|
||||
- [Beatrice v2](https://prj-beatrice.com/) (only for v2)
|
||||
-
|
||||
1. 이 소프트웨어는 네트워크를 통한 사용도 가능하며, 게임 등 부하가 큰 애플리케이션과 동시에 사용할 경우 음성 변화 처리의 부하를 외부로 돌릴 수도 있습니다.
|
||||
|
||||

|
||||
|
||||
3. 여러 플랫폼을 지원합니다.
|
||||
|
||||
- Windows, Mac(M1), Linux, Google Colab (MMVC만 지원)
|
||||
## 관련 소프트웨어
|
||||
- [실시간 음성 변조기 VCClient](https://github.com/w-okada/voice-changer)
|
||||
- [텍스트 읽기 소프트웨어 TTSClient](https://github.com/w-okada/ttsclient)
|
||||
- [실시간 음성 인식 소프트웨어 ASRClient](https://github.com/w-okada/asrclient)
|
||||
# 사용 방법
|
||||
|
||||
크게 두 가지 방법으로 사용할 수 있습니다. 난이도 순서는 다음과 같습니다.
|
||||
|
||||
- 사전 빌드된 Binary 사용
|
||||
- Docker, Anaconda 등으로 구축된 개발 환경에서 사용
|
||||
|
||||
이 소프트웨어나 MMVC에 익숙하지 않은 분들은 위에서부터 차근차근 익숙해지길 추천합니다.
|
||||
|
||||
## (1) 사전 빌드된 Binary(파일) 사용
|
||||
|
||||
- 실행 형식 바이너리를 다운로드하여 실행할 수 있습니다.
|
||||
|
||||
- 튜토리얼은 [이곳](tutorials/tutorial_rvc_ko_latest.md)을 확인하세요。([네트워크 문제 해결법](https://github.com/w-okada/voice-changer/blob/master/tutorials/trouble_shoot_communication_ko.md))
|
||||
|
||||
- [Google Colaboratory](https://github.com/w-okada/voice-changer/tree/v.2/w_okada's_Voice_Changer_version_2_x.ipynb) で簡単にお試しいただけるようになりました。左上の Open in Colab のボタンから起動できます。
|
||||
|
||||
<img src="https://github.com/w-okada/voice-changer/assets/48346627/3f092e2d-6834-42f6-bbfd-7d389111604e" width="400" height="150">
|
||||
|
||||
- Windows 버전과 Mac 버전을 제공하고 있습니다. [Hugging Face](https://huggingface.co/wok000/vcclient000/tree/main)에서 다운로드할 수 있습니다.
|
||||
- Windows용 v2
|
||||
- `vcclient_win_std_xxx.zip`를 다운로드하여 사용하세요. GPU를 사용하지 않고도 (어느 정도 고성능의) CPU를 사용한 음성 변환이나, DirectML을 사용해 GPU(AMD, Nvidia)를 활용한 음성 변환이 가능합니다. v2에서는 torch와 onnx 모두를 지원합니다.
|
||||
- Nvidia GPU를 가지고 계신 분들은 `vcclient_win_cuda_xxx.zip`를 사용하시면 더 빠른 음성 변환이 가능합니다.
|
||||
- Mac (Apple Silicon)용 v2
|
||||
- `vcclient_mac_xxx.zip`를 다운로드하여 사용하세요.
|
||||
- v1
|
||||
- Windows와 NVIDIA GPU를 사용하는 분은 ONNX(cpu, cuda), PyTorch(cpu, cuda)를 다운로드하세요.
|
||||
- Windows와 AMD/Intel GPU를 사용하는 분은 ONNX(cpu, DirectML), PyTorch(cpu, cuda)를 다운로드하세요 AMD/Intel GPU는 ONNX 모델을 사용할 때만 적용됩니다.
|
||||
- 그 외 GPU도 PyTorch, Onnxruntime가 지원할 경우에만 적용됩니다.
|
||||
- Windows에서 GPU를 사용하지 않는 분은 ONNX(cpu, cuda), PyTorch(cpu, cuda)를 다운로드하세요.
|
||||
|
||||
- Windows 버전은 다운로드한 zip 파일의 압축을 풀고 `start_http.bat`를 실행하세요.
|
||||
|
||||
- Mac 버전은 다운로드한 파일을 풀고 `startHttp.command`를 실행하세요. 확인되지 않은 개발자 메시지가 나오면 다시 control 키를 누르고 클릭해 실행하세요(or 오른쪽 클릭으로 실행하세요).
|
||||
|
||||
- 처음 실행할 때는 인터넷으로 여러 데이터를 다운로드합니다. 다운로드할 때 시간이 좀 걸릴 수 있습니다. 다운로드가 완료되면 브라우저가 실행됩니다.
|
||||
|
||||
- 원격으로 접속할 때는 http 대신 https `.bat` 파일(win)、`.command` 파일(mac)을 실행하세요.
|
||||
|
||||
- DDPS-SVC의 encoder는 hubert-soft만 지원합니다.
|
||||
|
||||
|
||||
## (2) Docker나 Anaconda 등으로 구축된 개발 환경에서 사용
|
||||
|
||||
이 리포지토리를 클론해 사용할 수 있습니다. Windows에서는 WSL2 환경 구축이 필수입니다. 또한, WSL2 상에 Docker나 Anaconda 등의 가상환경 구축이 필요합니다. Mac에서는 Anaconda 등의 Python 가상환경 구축이 필요합니다. 사전 준비가 필요하지만, 많은 환경에서 이 방법이 가장 빠르게 작동합니다. **<font color="red"> GPU가 없어도 나름 최근 출시된 CPU가 있다면 충분히 작동할 가능성이 있습니다</font>(아래 실시간성 항목 참조)**.
|
||||
|
||||
[WSL2와 Docker 설치 설명 영상](https://youtu.be/POo_Cg0eFMU)
|
||||
|
||||
[WSL2와 Anaconda 설치 설명 영상](https://youtu.be/fba9Zhsukqw)
|
||||
|
||||
Docker에서 실행은 [Docker를 사용](docker_vcclient/README_ko.md)을 참고해 서버를 구동하세요.
|
||||
|
||||
Anaconda 가상 환경에서 실행은 [서버 개발자용 문서](README_dev_ko.md)를 참고해 서버를 구동하세요.
|
||||
|
||||
# 문제 해결법
|
||||
|
||||
- [통신편](tutorials/trouble_shoot_communication_ko.md)
|
||||
|
||||
|
||||
# 개발자 서명에 대하여
|
||||
|
||||
이 소프트웨어는 개발자 서명이 없습니다. 本ソフトウェアは開発元の署名しておりません。下記のように警告が出ますが、コントロールキーを押しながらアイコンをクリックすると実行できるようになります。これは Apple のセキュリティポリシーによるものです。実行は自己責任となります。
|
||||
|
||||

|
||||
(이미지 번역: ctrl을 누른 채로 클릭)
|
||||
|
||||
# 감사의 말
|
||||
|
||||
- [立ちずんだもん素材](https://seiga.nicovideo.jp/seiga/im10792934)
|
||||
- [いらすとや](https://www.irasutoya.com/)
|
||||
- [つくよみちゃん](https://tyc.rei-yumesaki.net/)
|
||||
|
||||
```
|
||||
이 소프트웨어의 음성 합성에는 무료 소재 캐릭터 「つくよみちゃん(츠쿠요미 짱)」이 무료 공개하고 있는 음성 데이터를 사용했습니다.■츠쿠요미 짱 말뭉치(CV.夢前黎)
|
||||
https://tyc.rei-yumesaki.net/material/corpus/
|
||||
© Rei Yumesaki
|
||||
```
|
||||
|
||||
- [あみたろの声素材工房](https://amitaro.net/)
|
||||
- [れぷりかどーる](https://kikyohiroto1227.wixsite.com/kikoto-utau)
|
||||
|
||||
# 이용약관
|
||||
|
||||
- 실시간 음성 변환기 츠쿠요미 짱은 츠쿠요미 짱 말뭉치 이용약관에 따라 다음과 같은 목적으로 변환 후 음성을 사용하는 것을 금지합니다.
|
||||
|
||||
```
|
||||
|
||||
■사람을 비판·공격하는 행위. ("비판·공격"의 정의는 츠쿠요미 짱 캐릭터 라이센스에 준합니다)
|
||||
|
||||
■특정 정치적 입장·종교·사상에 대한 찬반을 논하는 행위.
|
||||
|
||||
■자극적인 표현물을 무분별하게 공개하는 행위.
|
||||
|
||||
■타인에게 2차 창작(소재로서의 활용)을 허가하는 형태로 공개하는 행위.
|
||||
※감상용 작품으로서 배포·판매하는 건 문제없습니다.
|
||||
```
|
||||
|
||||
- 실시간 음성 변환기 아미타로는 あみたろの声素材工房(아미타로의 음성 소재 공방)의 다음 이용약관에 따릅니다. 자세한 내용은 [이곳](https://amitaro.net/voice/faq/#index_id6)에 있습니다.
|
||||
|
||||
```
|
||||
아미타로의 음성 소재나 말뭉치 음성으로 음성 모델을 만들거나, 음성 변환기나 말투 변환기 등을 사용해 본인 목소리를 아미타로의 목소리로 변환해 사용하는 것도 괜찮습니다.
|
||||
|
||||
단, 그 경우에는 반드시 아미타로(혹은 코하루네 아미)의 음성으로 변환한 것을 명시하고, 아미타로(및 코하루네 아미)가 말하는 것이 아님을 누구나 알 수 있도록 하십시오.
|
||||
또한 아미타로의 음성으로 말하는 내용은 음성 소재 이용약관의 범위 내에서만 사용해야 하며, 민감한 발언은 삼가십시오.
|
||||
```
|
||||
|
||||
- 실시간 음성 변환기 키코토 마히로는 れぷりかどーる(레플리카 돌)의 이용약관에 따릅니다. 자세한 내용은 [이곳](https://kikyohiroto1227.wixsite.com/kikoto-utau/ter%EF%BD%8Ds-of-service)에 있습니다.
|
||||
|
||||
# 면책 사항
|
||||
|
||||
이 소프트웨어의 사용 또는 사용 불능으로 인해 발생한 직접 손해·간접 손해·파생적 손해·결과적 손해 또는 특별 손해에 대해 모든 책임을 지지 않습니다.
|
||||
|
||||
# (1) 레코더(트레이닝용 음성 녹음 앱)
|
||||
|
||||
MMVC 트레이닝용 음성을 간단하게 녹음할 수 있는 앱입니다.
|
||||
Github Pages에서 실행할 수 있어서 브라우저만 있으면 다양한 플랫폼에서 사용할 수 있습니다.
|
||||
녹음한 데이터는 브라우저에 저장됩니다. 외부로 유출되지 않습니다.
|
||||
|
||||
[녹음 앱 on Github Pages](https://w-okada.github.io/voice-changer/)
|
||||
|
||||
[설명 영상](https://youtu.be/s_GirFEGvaA)
|
||||
|
||||
# 이전 버전
|
||||
|
||||
| Version | OS | 프레임워크 | link | 지원 VC | 파일 크기 |
|
||||
| ---------- | --- | --------------------------------- | ---------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | --------- |
|
||||
| v.1.5.2.9e | mac | ONNX(cpu), PyTorch(cpu,mps) | [normal](https://drive.google.com/uc?id=1W0d7I7619PcO7kjb1SPXp6MmH5Unvd78&export=download) \*1 | MMVC v.1.5.x, MMVC v.1.3.x, so-vits-svc 4.0, RVC | 796MB |
|
||||
| | win | ONNX(cpu,cuda), PyTorch(cpu,cuda) | [normal](https://drive.google.com/uc?id=1tmTMJRRggS2Sb4goU-eHlRvUBR88RZDl&export=download) \*1 | MMVC v.1.5.x, MMVC v.1.3.x, so-vits-svc 4.0, so-vits-svc 4.0v2, RVC, DDSP-SVC | 2872MB |
|
||||
| v.1.5.3.1 | mac | ONNX(cpu), PyTorch(cpu,mps) | [normal](https://drive.google.com/uc?id=1oswF72q_cQQeXhIn6W275qLnoBAmcrR_&export=download) \*1 | MMVC v.1.5.x, MMVC v.1.3.x, so-vits-svc 4.0, RVC | 796MB |
|
||||
| | win | ONNX(cpu,cuda), PyTorch(cpu,cuda) | [normal](https://drive.google.com/uc?id=1AWjDhW4w2Uljp1-9P8YUJBZsIlnhkJX2&export=download) \*1 | MMVC v.1.5.x, MMVC v.1.3.x, so-vits-svc 4.0, so-vits-svc 4.0v2, RVC, DDSP-SVC | 2872MB |
|
||||
|
||||
# For Contributor
|
||||
|
||||
이 리포지토리는 [CLA](https://raw.githubusercontent.com/w-okada/voice-changer/master/LICENSE-CLA)를 설정했습니다.
|
119
README_ru.md
Normal file
@ -0,0 +1,119 @@
|
||||
[Японский](/README_ja.md) [Корейский](/README_ko.md) [Английский](/README_en.md)
|
||||
|
||||
## Что нового!
|
||||
- Мы выпустили продукт-сестру - клиент Text To Speech.
|
||||
- Вы можете насладиться генерацией голоса через простой интерфейс.
|
||||
- Подробнее [здесь](https://github.com/w-okada/ttsclient).
|
||||
- Код тренировки Beatrice V2 теперь доступен!
|
||||
- [Репозиторий кода тренировки](https://huggingface.co/fierce-cats/beatrice-trainer)
|
||||
- [Версия для Colab](https://github.com/w-okada/beatrice-trainer-colab)
|
||||
- v.2.0.70-beta (only for m1 mac)
|
||||
- [HERE](https://github.com/w-okada/voice-changer/tree/v.2)
|
||||
- new feature:
|
||||
- В версии VCClient для Mac на базе M1 теперь поддерживается Beatrice v2 beta.1.
|
||||
- v.2.0.69-beta (only for win)
|
||||
- [HERE](https://github.com/w-okada/voice-changer/tree/v.2)
|
||||
- Исправления ошибок:
|
||||
- Исправлена ошибка, из-за которой кнопка запуска не отображалась в случае некоторых исключений
|
||||
- Настроен выходной буфер для режима серверного устройства
|
||||
- Исправлена ошибка, при которой изменялась частота дискретизации при изменении настроек в режиме серверного устройства
|
||||
- Исправлена ошибка при использовании японского hubert
|
||||
- Прочее:
|
||||
- Добавлен фильтр API хоста (выделено) для режима серверного устройства
|
||||
- v.2.0.65-beta
|
||||
- [HERE](https://github.com/w-okada/voice-changer/tree/v.2)
|
||||
- new feature: We have supported Beatrice v2 beta.1, enabling even higher quality voice conversion.
|
||||
|
||||
# Что такое VC Клиент
|
||||
|
||||
1. Это клиентское ПО для выполнения преобразования голоса в реальном времени с использованием различных AI для преобразования голоса. Поддерживаемые AI:
|
||||
- [MMVC](https://github.com/isletennos/MMVC_Trainer) (только v1)
|
||||
- [so-vits-svc](https://github.com/svc-develop-team/so-vits-svc) (только v1)
|
||||
- [RVC (Retrieval-based Voice Conversion)](https://github.com/liujing04/Retrieval-based-Voice-Conversion-WebUI)
|
||||
- [DDSP-SVC](https://github.com/yxlllc/DDSP-SVC) (только v1)
|
||||
- [Beatrice JVS Corpus Edition](https://prj-beatrice.com/) * экспериментальный * (не по лицензии MIT, см. [readme](https://github.com/w-okada/voice-changer/blob/master/server/voice_changer/Beatrice/)), только для Windows, зависит от процессора (только v1)
|
||||
- [Beatrice v2](https://prj-beatrice.com/) (только v2)
|
||||
|
||||
2. Распределение нагрузки между разными ПК
|
||||
Реализация преобразования голоса работает по схеме "сервер-клиент". Вы можете запустить сервер MMVC на отдельном ПК для минимизации влияния на другие ресурсоёмкие процессы, такие как стриминг.
|
||||
|
||||

|
||||
|
||||
3. Кроссплатформенная совместимость
|
||||
Поддержка Windows, Mac (включая Apple Silicon M1), Linux и Google Colaboratory.
|
||||
|
||||
# Как использовать
|
||||
|
||||
Это приложение для изменения голоса с использованием MMVC и so-vits-svc.
|
||||
|
||||
Есть два основных способа использования, в порядке сложности:
|
||||
|
||||
- Использование готового исполняемого файла
|
||||
- Настройка окружения с Docker или Anaconda
|
||||
|
||||
## (1) Использование готовых исполняемых файлов
|
||||
|
||||
- Вы можете скачать и запустить исполняемые файлы.
|
||||
|
||||
- Смотрите [здесь](tutorials/tutorial_rvc_en_latest.md) для получения руководства. ([устранение неполадок](https://github.com/w-okada/voice-changer/blob/master/tutorials/trouble_shoot_communication_ja.md))
|
||||
|
||||
- Теперь попробовать можно на [Google Colaboratory](https://github.com/w-okada/voice-changer/tree/v.2/w_okada's_Voice_Changer_version_2_x.ipynb) (требуется аккаунт ngrok). Вы можете запустить его через кнопку "Открыть в Colab" в верхнем левом углу.
|
||||
|
||||
<img src="https://github.com/w-okada/voice-changer/assets/48346627/3f092e2d-6834-42f6-bbfd-7d389111604e" width="400" height="150">
|
||||
|
||||
- Мы предлагаем версии для Windows и Mac на [hugging face](https://huggingface.co/wok000/vcclient000/tree/main)
|
||||
- v2 для Windows
|
||||
- Пожалуйста, скачайте и используйте `vcclient_win_std_xxx.zip`. Преобразование голоса можно выполнять с использованием мощного процессора без GPU или с использованием DirectML для GPU (AMD, Nvidia). v2 поддерживает как torch, так и onnx.
|
||||
- Если у вас Nvidia GPU, скачайте `vcclient_win_cuda_xxx.zip` для более быстрого преобразования.
|
||||
- v2 для Mac (Apple Silicon)
|
||||
- Пожалуйста, скачайте и используйте `vcclient_mac_xxx.zip`.
|
||||
- v1
|
||||
- Для Windows с Nvidia GPU скачайте ONNX (cpu, cuda), PyTorch (cpu, cuda).
|
||||
- Для Windows с AMD/Intel GPU скачайте ONNX (cpu, DirectML) и PyTorch (cpu, cuda). AMD/Intel GPU поддерживаются только для ONNX моделей.
|
||||
|
||||
- Для пользователей Windows: после распаковки zip-файла запустите соответствующий `start_http.bat` файл.
|
||||
|
||||
- Для Mac: после распаковки zip-файла дважды щёлкните на `startHttp.command`. Если появится сообщение о невозможности проверки разработчика, нажмите Ctrl и повторно запустите.
|
||||
|
||||
- Если подключаетесь удалённо, используйте `.command` (Mac) или `.bat` (Windows) файл с https вместо http.
|
||||
|
||||
- Энкодер DDPS-SVC поддерживает только hubert-soft.
|
||||
|
||||
- [Скачать с hugging face](https://huggingface.co/wok000/vcclient000/tree/main)
|
||||
|
||||
## (2) Использование после настройки окружения с Docker или Anaconda
|
||||
|
||||
Клонируйте этот репозиторий и используйте его. Для Windows требуется настройка WSL2. Для Mac нужно настроить виртуальные среды Python, например Anaconda. Этот метод обеспечивает наивысшую скорость в большинстве случаев. **<font color="red"> Даже без GPU можно получить достаточную производительность на современном процессоре </font>(смотрите раздел о производительности в реальном времени ниже)**.
|
||||
|
||||
[Видео-инструкция по установке WSL2 и Docker](https://youtu.be/POo_Cg0eFMU)
|
||||
|
||||
[Видео-инструкция по установке WSL2 и Anaconda](https://youtu.be/fba9Zhsukqw)
|
||||
|
||||
Для запуска Docker смотрите [start docker](docker_vcclient/README_en.md).
|
||||
|
||||
Для запуска на Anaconda venv смотрите [руководство разработчика](README_dev_ru.md).
|
||||
|
||||
Для запуска на Linux с AMD GPU смотрите [руководство](tutorials/tutorial_anaconda_amd_rocm.md).
|
||||
|
||||
# Подпись программного обеспечения
|
||||
|
||||
Это ПО не подписано разработчиком. Появится предупреждение, но его можно запустить, нажав на иконку с удержанием клавиши Ctrl. Это связано с политикой безопасности Apple. Использование ПО на ваш риск.
|
||||
|
||||

|
||||
|
||||
https://user-images.githubusercontent.com/48346627/212569645-e30b7f4e-079d-4504-8cf8-7816c5f40b00.mp4
|
||||
|
||||
# Благодарности
|
||||
|
||||
- [Материалы Tachizunda-mon](https://seiga.nicovideo.jp/seiga/im10792934)
|
||||
- [Irasutoya](https://www.irasutoya.com/)
|
||||
- [Tsukuyomi-chan](https://tyc.rei-yumesaki.net)
|
||||
|
||||
> Это ПО использует голосовые данные бесплатного материала персонажа "Цукуёми-тян", предоставленного CV. Юмесаки Рэй.
|
||||
>
|
||||
> - Корпус Цукуёми-тян (CV. Юмесаки Рэй)
|
||||
>
|
||||
> https://tyc.rei-yumesaki.net/material/corpus/
|
||||
>
|
||||
> Авторское право. Юмесаки Рэй, Все права защищены.
|
||||
|
206
Realtime_Voice_Changer_on_Colab.ipynb
Normal file
@ -0,0 +1,206 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "view-in-github",
|
||||
"colab_type": "text"
|
||||
},
|
||||
"source": [
|
||||
"<a href=\"https://colab.research.google.com/github/w-okada/voice-changer/blob/master/Realtime_Voice_Changer_on_Colab.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### [w-okada's Voice Changer](https://github.com/w-okada/voice-changer) | **Colab**\n",
|
||||
"\n",
|
||||
"---\n",
|
||||
"\n",
|
||||
"## **⬇ VERY IMPORTANT ⬇**\n",
|
||||
"\n",
|
||||
"You can use the following settings for better results:\n",
|
||||
"\n",
|
||||
"If you're using a index: `f0: RMVPE_ONNX | Chunk: 112 or higher | Extra: 8192`<br>\n",
|
||||
"If you're not using a index: `f0: RMVPE_ONNX | Chunk: 96 or higher | Extra: 16384`<br>\n",
|
||||
"**Don't forget to select a T4 GPU in the GPU field, <b>NEVER</b> use CPU!\n",
|
||||
"> Seems that PTH models performance better than ONNX for now, you can still try ONNX models and see if it satisfies you\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"*You can always [click here](https://github.com/YunaOneeChan/Voice-Changer-Settings) to check if these settings are up-to-date*\n",
|
||||
"\n",
|
||||
"---\n",
|
||||
"\n",
|
||||
"### <font color=red>⬇ Always use Colab GPU! (**IMPORTANT!**) ⬇</font>\n",
|
||||
"You need to use a Colab GPU so the Voice Changer can work faster and better\\\n",
|
||||
"Use the menu above and click on **Runtime** » **Change runtime** » **Hardware acceleration** to select a GPU (**T4 is the free one**)\n",
|
||||
"\n",
|
||||
"---\n",
|
||||
"**Credits**<br>\n",
|
||||
"Realtime Voice Changer by [w-okada](https://github.com/w-okada)<br>\n",
|
||||
"Notebook files updated by [rafacasari](https://github.com/Rafacasari)<br>\n",
|
||||
"Recommended settings by [YunaOneeChan](https://github.com/YunaOneeChan)\n",
|
||||
"\n",
|
||||
"**Need help?** [AI Hub Discord](https://discord.gg/aihub) » ***#help-realtime-vc***\n",
|
||||
"\n",
|
||||
"---"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "Lbbmx_Vjl0zo"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"# @title Clone repository and install dependencies\n",
|
||||
"# @markdown This first step will download the latest version of Voice Changer and install the dependencies. **It can take some time to complete.**\n",
|
||||
"%cd /content/\n",
|
||||
"\n",
|
||||
"!pip install colorama --quiet\n",
|
||||
"from colorama import Fore, Style\n",
|
||||
"import os\n",
|
||||
"\n",
|
||||
"print(f\"{Fore.CYAN}> Cloning the repository...{Style.RESET_ALL}\")\n",
|
||||
"!git clone https://github.com/w-okada/voice-changer.git --quiet\n",
|
||||
"print(f\"{Fore.GREEN}> Successfully cloned the repository!{Style.RESET_ALL}\")\n",
|
||||
"%cd voice-changer/server/\n",
|
||||
"\n",
|
||||
"print(f\"{Fore.CYAN}> Installing libportaudio2...{Style.RESET_ALL}\")\n",
|
||||
"!apt-get -y install libportaudio2 -qq\n",
|
||||
"\n",
|
||||
"print(f\"{Fore.CYAN}> Installing pre-dependencies...{Style.RESET_ALL}\")\n",
|
||||
"# Install dependencies that are missing from requirements.txt and pyngrok\n",
|
||||
"!pip install faiss-gpu fairseq pyngrok --quiet\n",
|
||||
"!pip install pyworld --no-build-isolation --quiet\n",
|
||||
"print(f\"{Fore.CYAN}> Installing dependencies from requirements.txt...{Style.RESET_ALL}\")\n",
|
||||
"!pip install -r requirements.txt --quiet\n",
|
||||
"\n",
|
||||
"print(f\"{Fore.GREEN}> Successfully installed all packages!{Style.RESET_ALL}\")"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "86wTFmqsNMnD",
|
||||
"cellView": "form",
|
||||
"_kg_hide-output": false,
|
||||
"execution": {
|
||||
"iopub.status.busy": "2023-09-14T04:01:17.308284Z",
|
||||
"iopub.execute_input": "2023-09-14T04:01:17.308682Z",
|
||||
"iopub.status.idle": "2023-09-14T04:08:08.475375Z",
|
||||
"shell.execute_reply.started": "2023-09-14T04:01:17.308652Z",
|
||||
"shell.execute_reply": "2023-09-14T04:08:08.473827Z"
|
||||
},
|
||||
"trusted": true
|
||||
},
|
||||
"execution_count": null,
|
||||
"outputs": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"# @title Start Server **using ngrok**\n",
|
||||
"# @markdown This cell will start the server, the first time that you run it will download the models, so it can take a while (~1-2 minutes)\n",
|
||||
"\n",
|
||||
"# @markdown ---\n",
|
||||
"# @markdown You'll need a ngrok account, but <font color=green>**it's free**</font> and easy to create!\n",
|
||||
"# @markdown ---\n",
|
||||
"# @markdown **1** - Create a <font color=green>**free**</font> account at [ngrok](https://dashboard.ngrok.com/signup) or **login with Google/Github account**\\\n",
|
||||
"# @markdown **2** - If you didn't logged in with Google/Github, you will need to **verify your e-mail**!\\\n",
|
||||
"# @markdown **3** - Click [this link](https://dashboard.ngrok.com/get-started/your-authtoken) to get your auth token, and place it here:\n",
|
||||
"Token = '' # @param {type:\"string\"}\n",
|
||||
"# @markdown **4** - *(optional)* Change to a region near to you or keep at United States if increase latency\\\n",
|
||||
"# @markdown `Default Region: us - United States (Ohio)`\n",
|
||||
"Region = \"us - United States (Ohio)\" # @param [\"ap - Asia/Pacific (Singapore)\", \"au - Australia (Sydney)\",\"eu - Europe (Frankfurt)\", \"in - India (Mumbai)\",\"jp - Japan (Tokyo)\",\"sa - South America (Sao Paulo)\", \"us - United States (Ohio)\"]\n",
|
||||
"\n",
|
||||
"#@markdown **5** - *(optional)* Other options:\n",
|
||||
"ClearConsole = True # @param {type:\"boolean\"}\n",
|
||||
"\n",
|
||||
"# ---------------------------------\n",
|
||||
"# DO NOT TOUCH ANYTHING DOWN BELOW!\n",
|
||||
"# ---------------------------------\n",
|
||||
"\n",
|
||||
"%cd /content/voice-changer/server\n",
|
||||
"\n",
|
||||
"from pyngrok import conf, ngrok\n",
|
||||
"MyConfig = conf.PyngrokConfig()\n",
|
||||
"MyConfig.auth_token = Token\n",
|
||||
"MyConfig.region = Region[0:2]\n",
|
||||
"#conf.get_default().authtoken = Token\n",
|
||||
"#conf.get_default().region = Region\n",
|
||||
"conf.set_default(MyConfig);\n",
|
||||
"\n",
|
||||
"import subprocess, threading, time, socket, urllib.request\n",
|
||||
"PORT = 8000\n",
|
||||
"\n",
|
||||
"from pyngrok import ngrok\n",
|
||||
"ngrokConnection = ngrok.connect(PORT)\n",
|
||||
"public_url = ngrokConnection.public_url\n",
|
||||
"\n",
|
||||
"from IPython.display import clear_output\n",
|
||||
"\n",
|
||||
"def wait_for_server():\n",
|
||||
" while True:\n",
|
||||
" time.sleep(0.5)\n",
|
||||
" sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n",
|
||||
" result = sock.connect_ex(('127.0.0.1', PORT))\n",
|
||||
" if result == 0:\n",
|
||||
" break\n",
|
||||
" sock.close()\n",
|
||||
" if ClearConsole:\n",
|
||||
" clear_output()\n",
|
||||
" print(\"--------- SERVER READY! ---------\")\n",
|
||||
" print(\"Your server is available at:\")\n",
|
||||
" print(public_url)\n",
|
||||
" print(\"---------------------------------\")\n",
|
||||
"\n",
|
||||
"threading.Thread(target=wait_for_server, daemon=True).start()\n",
|
||||
"\n",
|
||||
"!python3 MMVCServerSIO.py \\\n",
|
||||
" -p {PORT} \\\n",
|
||||
" --https False \\\n",
|
||||
" --content_vec_500 pretrain/checkpoint_best_legacy_500.pt \\\n",
|
||||
" --content_vec_500_onnx pretrain/content_vec_500.onnx \\\n",
|
||||
" --content_vec_500_onnx_on true \\\n",
|
||||
" --hubert_base pretrain/hubert_base.pt \\\n",
|
||||
" --hubert_base_jp pretrain/rinna_hubert_base_jp.pt \\\n",
|
||||
" --hubert_soft pretrain/hubert/hubert-soft-0d54a1f4.pt \\\n",
|
||||
" --nsf_hifigan pretrain/nsf_hifigan/model \\\n",
|
||||
" --crepe_onnx_full pretrain/crepe_onnx_full.onnx \\\n",
|
||||
" --crepe_onnx_tiny pretrain/crepe_onnx_tiny.onnx \\\n",
|
||||
" --rmvpe pretrain/rmvpe.pt \\\n",
|
||||
" --model_dir model_dir \\\n",
|
||||
" --samples samples.json\n",
|
||||
"\n",
|
||||
"ngrok.disconnect(ngrokConnection.public_url)"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "lLWQuUd7WW9U",
|
||||
"cellView": "form",
|
||||
"_kg_hide-input": false,
|
||||
"scrolled": true,
|
||||
"trusted": true
|
||||
},
|
||||
"execution_count": null,
|
||||
"outputs": []
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"provenance": [],
|
||||
"private_outputs": true,
|
||||
"include_colab_link": true,
|
||||
"gpuType": "T4",
|
||||
"collapsed_sections": [
|
||||
"iuf9pBHYpTn-"
|
||||
]
|
||||
},
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
},
|
||||
"accelerator": "GPU"
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 0
|
||||
}
|
1579
SoftVcDemo.ipynb
@ -1,409 +0,0 @@
|
||||
{
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 0,
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"name": "VoiceChangerDemo",
|
||||
"provenance": [],
|
||||
"authorship_tag": "ABX9TyOc15otxqkeLfxiyox8JliU",
|
||||
"include_colab_link": true
|
||||
},
|
||||
"kernelspec": {
|
||||
"name": "python3",
|
||||
"display_name": "Python 3"
|
||||
},
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
},
|
||||
"accelerator": "GPU",
|
||||
"gpuClass": "standard"
|
||||
},
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "view-in-github",
|
||||
"colab_type": "text"
|
||||
},
|
||||
"source": [
|
||||
"<a href=\"https://colab.research.google.com/github/w-okada/voice-changer/blob/dev/VoiceChangerDemo.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"MMVCプレイヤー(普通版)\n",
|
||||
"---\n",
|
||||
"\n",
|
||||
"このノートはColab上でMMVCのボイチェンを行うノートです。\n",
|
||||
"\n",
|
||||
"正式版はローカルPCのDocker上で動かすアプリケーションです。\n",
|
||||
"\n",
|
||||
"正式版は、多くの場合より少ないタイムラグで滑らかに音声を変換できます。\n",
|
||||
"\n",
|
||||
"詳細な使用方法はこちらの[リポジトリ](https://github.com/w-okada/voice-changer)からご確認ください。\n"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "Lbbmx_Vjl0zo"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"# GPUを確認\n",
|
||||
"GPUを用いたほうが高速に処理が行えます。\n",
|
||||
"\n",
|
||||
"下記のコマンドでGPUが確認できない場合は、上のメニューから\n",
|
||||
"\n",
|
||||
"「ランタイム」→「ランタイムの変更」→「ハードウェア アクセラレータ」\n",
|
||||
"\n",
|
||||
"でGPUを選択してください。"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "oUKi1NYMmXrr"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"# (1) GPUの確認\n",
|
||||
"!nvidia-smi"
|
||||
],
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"base_uri": "https://localhost:8080/"
|
||||
},
|
||||
"id": "vV1t7PBRm-o6",
|
||||
"outputId": "0ca1a6a2-95c1-429f-bb6a-adbf71bcda02"
|
||||
},
|
||||
"execution_count": 1,
|
||||
"outputs": [
|
||||
{
|
||||
"output_type": "stream",
|
||||
"name": "stdout",
|
||||
"text": [
|
||||
"Sat Jan 14 10:57:42 2023 \n",
|
||||
"+-----------------------------------------------------------------------------+\n",
|
||||
"| NVIDIA-SMI 460.32.03 Driver Version: 460.32.03 CUDA Version: 11.2 |\n",
|
||||
"|-------------------------------+----------------------+----------------------+\n",
|
||||
"| GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC |\n",
|
||||
"| Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. |\n",
|
||||
"| | | MIG M. |\n",
|
||||
"|===============================+======================+======================|\n",
|
||||
"| 0 Tesla T4 Off | 00000000:00:04.0 Off | 0 |\n",
|
||||
"| N/A 63C P8 11W / 70W | 0MiB / 15109MiB | 0% Default |\n",
|
||||
"| | | N/A |\n",
|
||||
"+-------------------------------+----------------------+----------------------+\n",
|
||||
" \n",
|
||||
"+-----------------------------------------------------------------------------+\n",
|
||||
"| Processes: |\n",
|
||||
"| GPU GI CI PID Type Process name GPU Memory |\n",
|
||||
"| ID ID Usage |\n",
|
||||
"|=============================================================================|\n",
|
||||
"| No running processes found |\n",
|
||||
"+-----------------------------------------------------------------------------+\n"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"# 使用するモデルとコンフィグファイルの指定\n",
|
||||
"\n",
|
||||
"使用するトレーニング済みのモデルと、トレーニングで使用したコンフィグファイルのパスを指定してください。\n",
|
||||
"\n",
|
||||
"多くの場合はGoogle Driveに格納されているファイルを使用すると思います。その場合は、下の(2-2)のセルを実行してドライブをマウントしてください"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "mHvGrgaWnIPA"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"# (2-1) 使用するモデルとコンフィグファイルの指定\n",
|
||||
"if \"MODEL\" in locals():\n",
|
||||
" del MODEL\n",
|
||||
"if \"ONNX\" in locals():\n",
|
||||
" del ONNX\n",
|
||||
"\n",
|
||||
"CONFIG=\"/content/drive/MyDrive/VoiceChanger/config.json\"\n",
|
||||
"#MODEL=\"/content/drive/MyDrive/VoiceChanger/G_326000.pth\"\n",
|
||||
"ONNX=\"/content/drive/MyDrive/VoiceChanger/G_326000.onnx\""
|
||||
],
|
||||
"metadata": {
|
||||
"id": "nSXATMWYb4Ik"
|
||||
},
|
||||
"execution_count": 2,
|
||||
"outputs": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"base_uri": "https://localhost:8080/"
|
||||
},
|
||||
"id": "2wxD-gRSMU5R",
|
||||
"outputId": "0cca0ac1-4a3b-42da-a3c3-057d550e379f"
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"output_type": "stream",
|
||||
"name": "stdout",
|
||||
"text": [
|
||||
"Mounted at /content/drive\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"# (2-2) Google Driveのマウント\n",
|
||||
"from google.colab import drive\n",
|
||||
"drive.mount('/content/drive')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"# リポジトリのクローン\n",
|
||||
"リポジトリをクローンします"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "sLBfykjBnjWc"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"# (3) リポジトリのクローン\n",
|
||||
"!git clone --depth 1 https://github.com/w-okada/voice-changer.git -b v.1.3.5\n",
|
||||
"%cd voice-changer/server\n",
|
||||
"!git clone https://github.com/isletennos/MMVC_Client.git\n",
|
||||
"!cd MMVC_Client && git checkout 04f3fec4fd82dea6657026ec4e1cd80fb29a415c && cd -"
|
||||
],
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"base_uri": "https://localhost:8080/"
|
||||
},
|
||||
"id": "86wTFmqsNMnD",
|
||||
"outputId": "a249b913-3ffc-4b82-f62d-a856012f3562"
|
||||
},
|
||||
"execution_count": 4,
|
||||
"outputs": [
|
||||
{
|
||||
"output_type": "stream",
|
||||
"name": "stdout",
|
||||
"text": [
|
||||
"Cloning into 'voice-changer'...\n",
|
||||
"remote: Enumerating objects: 149, done.\u001b[K\n",
|
||||
"remote: Counting objects: 100% (149/149), done.\u001b[K\n",
|
||||
"remote: Compressing objects: 100% (134/134), done.\u001b[K\n",
|
||||
"remote: Total 149 (delta 20), reused 64 (delta 5), pack-reused 0\u001b[K\n",
|
||||
"Receiving objects: 100% (149/149), 1.56 MiB | 4.35 MiB/s, done.\n",
|
||||
"Resolving deltas: 100% (20/20), done.\n",
|
||||
"Note: checking out '4c6f7c00fa68d91e1ccdb07b7c35ce603b6b0ab2'.\n",
|
||||
"\n",
|
||||
"You are in 'detached HEAD' state. You can look around, make experimental\n",
|
||||
"changes and commit them, and you can discard any commits you make in this\n",
|
||||
"state without impacting any branches by performing another checkout.\n",
|
||||
"\n",
|
||||
"If you want to create a new branch to retain commits you create, you may\n",
|
||||
"do so (now or later) by using -b with the checkout command again. Example:\n",
|
||||
"\n",
|
||||
" git checkout -b <new-branch-name>\n",
|
||||
"\n",
|
||||
"/content/voice-changer/server\n",
|
||||
"Cloning into 'MMVC_Client'...\n",
|
||||
"remote: Enumerating objects: 594, done.\u001b[K\n",
|
||||
"remote: Counting objects: 100% (320/320), done.\u001b[K\n",
|
||||
"remote: Compressing objects: 100% (114/114), done.\u001b[K\n",
|
||||
"remote: Total 594 (delta 229), reused 261 (delta 203), pack-reused 274\u001b[K\n",
|
||||
"Receiving objects: 100% (594/594), 738.87 KiB | 18.02 MiB/s, done.\n",
|
||||
"Resolving deltas: 100% (351/351), done.\n",
|
||||
"Note: checking out '04f3fec4fd82dea6657026ec4e1cd80fb29a415c'.\n",
|
||||
"\n",
|
||||
"You are in 'detached HEAD' state. You can look around, make experimental\n",
|
||||
"changes and commit them, and you can discard any commits you make in this\n",
|
||||
"state without impacting any branches by performing another checkout.\n",
|
||||
"\n",
|
||||
"If you want to create a new branch to retain commits you create, you may\n",
|
||||
"do so (now or later) by using -b with the checkout command again. Example:\n",
|
||||
"\n",
|
||||
" git checkout -b <new-branch-name>\n",
|
||||
"\n",
|
||||
"HEAD is now at 04f3fec Merge pull request #30 from Mokuichi147/setupcheck\n",
|
||||
"/content/voice-changer/server\n"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"# モジュールのインストール\n",
|
||||
"\n",
|
||||
"必要なモジュールをインストールします。"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "8Na2PbLZSWgZ"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"# (5) 設定ファイルの確認\n",
|
||||
"!apt-get install -y libsndfile1-dev &> /dev/null\n",
|
||||
"!pip install fastapi &> /dev/null\n",
|
||||
"!pip install pyOpenSSL &> /dev/null\n",
|
||||
"!pip install python-multipart &> /dev/null\n",
|
||||
"!pip install python-socketio &> /dev/null\n",
|
||||
"!pip install uvicorn &> /dev/null\n",
|
||||
"!pip install websockets &> /dev/null\n",
|
||||
"!pip install onnxruntime-gpu &> /dev/null"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "LwZAAuqxX7yY"
|
||||
},
|
||||
"execution_count": 5,
|
||||
"outputs": []
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"# サーバの起動\n",
|
||||
"\n",
|
||||
"サーバを起動します。(6-1)\n",
|
||||
"\n",
|
||||
"サーバの起動状況を確認します。(6-2) \n",
|
||||
"\n",
|
||||
"このセルは繰り返し実行することになるのでCtrl+Retでセルを実行してください。\n",
|
||||
"\n",
|
||||
"アクセスできるようになるまで、1~2分かかるようです。コーヒーでも飲みに行きましょう。\n",
|
||||
"\n",
|
||||
"下記のようなテキストが表示されたら起動完了です。\n",
|
||||
"(warningは無視して問題ありません。)\n",
|
||||
"```\n",
|
||||
"/usr/local/lib/python3.8/dist-packages/onnxruntime/capi/onnxruntime_inference_collection.py:54: UserWarning: Specified provider 'OpenVINOExecutionProvider' is not in available provider names.Available providers: 'TensorrtExecutionProvider, CUDAExecutionProvider, CPUExecutionProvider'\n",
|
||||
" warnings.warn(\n",
|
||||
"/usr/local/lib/python3.8/dist-packages/onnxruntime/capi/onnxruntime_inference_collection.py:54: UserWarning: Specified provider 'DmlExecutionProvider' is not in available provider names.Available providers: 'TensorrtExecutionProvider, CUDAExecutionProvider, CPUExecutionProvider'\n",
|
||||
" warnings.warn(\n",
|
||||
"VoiceChanger Initialized (GPU_NUM:1, mps_enabled:False)\n",
|
||||
" Voice Changerを起動しています。\n",
|
||||
" -- 設定 -- \n",
|
||||
" CONFIG:/content/drive/MyDrive/VoiceChanger/config.json, MODEL:None ONNX_MODEL:/content/drive/MyDrive/VoiceChanger/G_326000.onnx```\n",
|
||||
"\n"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "-_2OcN9Borke"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"# (6-1) サーバの起動\n",
|
||||
"import random\n",
|
||||
"PORT = 10000 + random.randint(1, 9999)\n",
|
||||
"LOG_FILE = f\"LOG_FILE_{PORT}\"\n",
|
||||
"\n",
|
||||
"if \"MODEL\" in locals() and \"ONNX\" in locals():\n",
|
||||
" model_param = f\" -m {MODEL} -o {ONNX}\"\n",
|
||||
"elif \"MODEL\" in locals():\n",
|
||||
" model_param = f\" -m {MODEL}\"\n",
|
||||
"elif \"ONNX\" in locals():\n",
|
||||
" model_param = f\" -o {ONNX}\"\n",
|
||||
"else:\n",
|
||||
" model_param = f\"\"\n",
|
||||
"\n",
|
||||
"get_ipython().system_raw(f'python3 MMVCServerSIO.py -t MMVC -p {PORT} -c {CONFIG} {model_param} --https False --colab True >{LOG_FILE} 2>&1 &')\n",
|
||||
"#print(f\"PORT:{PORT}, LOG_FILE:{LOG_FILE}\")"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "iNOAB7zISI6J"
|
||||
},
|
||||
"execution_count": 6,
|
||||
"outputs": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"# (6-2) サーバの起動確認 (Ctrl+Retで実行)\n",
|
||||
"!tail -20 {LOG_FILE}"
|
||||
],
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"base_uri": "https://localhost:8080/"
|
||||
},
|
||||
"id": "chu06KpAjEK6",
|
||||
"outputId": "dab82a85-6d85-4a6c-ecee-82f458269862"
|
||||
},
|
||||
"execution_count": 13,
|
||||
"outputs": [
|
||||
{
|
||||
"output_type": "stream",
|
||||
"name": "stdout",
|
||||
"text": [
|
||||
"/usr/local/lib/python3.8/dist-packages/onnxruntime/capi/onnxruntime_inference_collection.py:54: UserWarning: Specified provider 'OpenVINOExecutionProvider' is not in available provider names.Available providers: 'TensorrtExecutionProvider, CUDAExecutionProvider, CPUExecutionProvider'\n",
|
||||
" warnings.warn(\n",
|
||||
"/usr/local/lib/python3.8/dist-packages/onnxruntime/capi/onnxruntime_inference_collection.py:54: UserWarning: Specified provider 'DmlExecutionProvider' is not in available provider names.Available providers: 'TensorrtExecutionProvider, CUDAExecutionProvider, CPUExecutionProvider'\n",
|
||||
" warnings.warn(\n",
|
||||
"VoiceChanger Initialized (GPU_NUM:1, mps_enabled:False)\n",
|
||||
"\u001b[32m Voice Changerを起動しています。\u001b[0m\n",
|
||||
"\u001b[34m -- 設定 -- \u001b[0m\n",
|
||||
"\u001b[34m CONFIG:/content/drive/MyDrive/VoiceChanger/config.json, MODEL:None ONNX_MODEL:/content/drive/MyDrive/VoiceChanger/G_326000.onnx\u001b[0m\n"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"# プロキシを起動\n",
|
||||
"ウェブサーバへのアクセスをするためのプロキシを起動します。\n",
|
||||
"\n",
|
||||
"表示されたURLをクリックして開くと別タブでアプリが開きます。\n",
|
||||
"\n",
|
||||
"Colabなので、ロードにある程度時間がかかります(30秒くらい)。"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "WhxcFLQEpctq"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"# (7) プロキシを起動\n",
|
||||
"from google.colab.output import eval_js\n",
|
||||
"proxy = eval_js( \"google.colab.kernel.proxyPort(\" + str(PORT) + \")\" )\n",
|
||||
"print(f\"{proxy}front/?colab=true\")"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "nkRjZm95l87C",
|
||||
"colab": {
|
||||
"base_uri": "https://localhost:8080/",
|
||||
"height": 34
|
||||
},
|
||||
"outputId": "67b0f1f9-6c29-4a7c-b51a-09b0d6fa73ce"
|
||||
},
|
||||
"execution_count": 14,
|
||||
"outputs": [
|
||||
{
|
||||
"output_type": "stream",
|
||||
"name": "stdout",
|
||||
"text": [
|
||||
"https://bw798xestd8-496ff2e9c6d22116-13755-colab.googleusercontent.com/front/?colab=true\n"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [],
|
||||
"metadata": {
|
||||
"id": "Jos5WZHGmz4s"
|
||||
},
|
||||
"execution_count": null,
|
||||
"outputs": []
|
||||
}
|
||||
]
|
||||
}
|
@ -1,334 +0,0 @@
|
||||
{
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 0,
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"provenance": [],
|
||||
"authorship_tag": "ABX9TyMvlihfFf4Lya4Hh98XmoBI",
|
||||
"include_colab_link": true
|
||||
},
|
||||
"kernelspec": {
|
||||
"name": "python3",
|
||||
"display_name": "Python 3"
|
||||
},
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
},
|
||||
"accelerator": "GPU",
|
||||
"gpuClass": "standard"
|
||||
},
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "view-in-github",
|
||||
"colab_type": "text"
|
||||
},
|
||||
"source": [
|
||||
"<a href=\"https://colab.research.google.com/github/w-okada/voice-changer/blob/dev/VoiceChangerDemo_Simple.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"MMVCプレイヤー(超簡単版)\n",
|
||||
"---\n",
|
||||
"\n",
|
||||
"このノートはColab上でMMVCのボイチェンを行うノートです。\n",
|
||||
"\n",
|
||||
"正式版はローカルPCのDocker上で動かすアプリケーションです。\n",
|
||||
"\n",
|
||||
"正式版は、多くの場合より少ないタイムラグで滑らかに音声を変換できます。\n",
|
||||
"\n",
|
||||
"詳細な使用方法はこちらの[リポジトリ](https://github.com/w-okada/voice-changer)からご確認ください。\n"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "Lbbmx_Vjl0zo"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"# GPUを確認\n",
|
||||
"GPUを用いたほうが高速に処理が行えます。\n",
|
||||
"\n",
|
||||
"下記のコマンドでGPUが確認できない場合は、上のメニューから\n",
|
||||
"\n",
|
||||
"「ランタイム」→「ランタイムの変更」→「ハードウェア アクセラレータ」\n",
|
||||
"\n",
|
||||
"でGPUを選択してください。"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "oUKi1NYMmXrr"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"# (1) GPUの確認\n",
|
||||
"!nvidia-smi"
|
||||
],
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"base_uri": "https://localhost:8080/"
|
||||
},
|
||||
"id": "vV1t7PBRm-o6",
|
||||
"outputId": "03507075-369d-4dc6-9b34-dfc37a5dcf6d"
|
||||
},
|
||||
"execution_count": 1,
|
||||
"outputs": [
|
||||
{
|
||||
"output_type": "stream",
|
||||
"name": "stdout",
|
||||
"text": [
|
||||
"Sat Jan 14 10:48:43 2023 \n",
|
||||
"+-----------------------------------------------------------------------------+\n",
|
||||
"| NVIDIA-SMI 460.32.03 Driver Version: 460.32.03 CUDA Version: 11.2 |\n",
|
||||
"|-------------------------------+----------------------+----------------------+\n",
|
||||
"| GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC |\n",
|
||||
"| Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. |\n",
|
||||
"| | | MIG M. |\n",
|
||||
"|===============================+======================+======================|\n",
|
||||
"| 0 Tesla T4 Off | 00000000:00:04.0 Off | 0 |\n",
|
||||
"| N/A 47C P8 10W / 70W | 0MiB / 15109MiB | 0% Default |\n",
|
||||
"| | | N/A |\n",
|
||||
"+-------------------------------+----------------------+----------------------+\n",
|
||||
" \n",
|
||||
"+-----------------------------------------------------------------------------+\n",
|
||||
"| Processes: |\n",
|
||||
"| GPU GI CI PID Type Process name GPU Memory |\n",
|
||||
"| ID ID Usage |\n",
|
||||
"|=============================================================================|\n",
|
||||
"| No running processes found |\n",
|
||||
"+-----------------------------------------------------------------------------+\n"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"# リポジトリのクローン\n",
|
||||
"リポジトリをクローンします"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "sLBfykjBnjWc"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"# (2) リポジトリのクローン\n",
|
||||
"!git clone --depth 1 https://github.com/w-okada/voice-changer.git -b v.1.3.5\n",
|
||||
"%cd voice-changer/server\n",
|
||||
"!git clone https://github.com/isletennos/MMVC_Client.git\n",
|
||||
"!cd MMVC_Client && git checkout 04f3fec4fd82dea6657026ec4e1cd80fb29a415c && cd -\n"
|
||||
],
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"base_uri": "https://localhost:8080/"
|
||||
},
|
||||
"id": "86wTFmqsNMnD",
|
||||
"outputId": "d65ffce7-99a5-4cb6-b7bd-cb7cff7f3eb3"
|
||||
},
|
||||
"execution_count": 2,
|
||||
"outputs": [
|
||||
{
|
||||
"output_type": "stream",
|
||||
"name": "stdout",
|
||||
"text": [
|
||||
"Cloning into 'voice-changer'...\n",
|
||||
"remote: Enumerating objects: 149, done.\u001b[K\n",
|
||||
"remote: Counting objects: 100% (149/149), done.\u001b[K\n",
|
||||
"remote: Compressing objects: 100% (134/134), done.\u001b[K\n",
|
||||
"remote: Total 149 (delta 20), reused 64 (delta 5), pack-reused 0\u001b[K\n",
|
||||
"Receiving objects: 100% (149/149), 1.56 MiB | 4.17 MiB/s, done.\n",
|
||||
"Resolving deltas: 100% (20/20), done.\n",
|
||||
"Note: checking out '4c6f7c00fa68d91e1ccdb07b7c35ce603b6b0ab2'.\n",
|
||||
"\n",
|
||||
"You are in 'detached HEAD' state. You can look around, make experimental\n",
|
||||
"changes and commit them, and you can discard any commits you make in this\n",
|
||||
"state without impacting any branches by performing another checkout.\n",
|
||||
"\n",
|
||||
"If you want to create a new branch to retain commits you create, you may\n",
|
||||
"do so (now or later) by using -b with the checkout command again. Example:\n",
|
||||
"\n",
|
||||
" git checkout -b <new-branch-name>\n",
|
||||
"\n",
|
||||
"/content/voice-changer/server\n",
|
||||
"Cloning into 'MMVC_Client'...\n",
|
||||
"remote: Enumerating objects: 594, done.\u001b[K\n",
|
||||
"remote: Counting objects: 100% (322/322), done.\u001b[K\n",
|
||||
"remote: Compressing objects: 100% (114/114), done.\u001b[K\n",
|
||||
"remote: Total 594 (delta 231), reused 263 (delta 205), pack-reused 272\u001b[K\n",
|
||||
"Receiving objects: 100% (594/594), 776.40 KiB | 6.87 MiB/s, done.\n",
|
||||
"Resolving deltas: 100% (352/352), done.\n",
|
||||
"Note: checking out '04f3fec4fd82dea6657026ec4e1cd80fb29a415c'.\n",
|
||||
"\n",
|
||||
"You are in 'detached HEAD' state. You can look around, make experimental\n",
|
||||
"changes and commit them, and you can discard any commits you make in this\n",
|
||||
"state without impacting any branches by performing another checkout.\n",
|
||||
"\n",
|
||||
"If you want to create a new branch to retain commits you create, you may\n",
|
||||
"do so (now or later) by using -b with the checkout command again. Example:\n",
|
||||
"\n",
|
||||
" git checkout -b <new-branch-name>\n",
|
||||
"\n",
|
||||
"HEAD is now at 04f3fec Merge pull request #30 from Mokuichi147/setupcheck\n",
|
||||
"/content/voice-changer/server\n"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"# モジュールのインストール\n",
|
||||
"\n",
|
||||
"必要なモジュールをインストールします。"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "8Na2PbLZSWgZ"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"# (3) 設定ファイルの確認\n",
|
||||
"!apt-get install -y libsndfile1-dev &> /dev/null\n",
|
||||
"!pip install fastapi &> /dev/null\n",
|
||||
"!pip install pyOpenSSL &> /dev/null\n",
|
||||
"!pip install python-multipart &> /dev/null\n",
|
||||
"!pip install python-socketio &> /dev/null\n",
|
||||
"!pip install uvicorn &> /dev/null\n",
|
||||
"!pip install websockets &> /dev/null\n",
|
||||
"!pip install onnxruntime-gpu &> /dev/null\n"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "LwZAAuqxX7yY"
|
||||
},
|
||||
"execution_count": 3,
|
||||
"outputs": []
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"# サーバの起動\n",
|
||||
"\n",
|
||||
"サーバを起動します。(4-1)\n",
|
||||
"\n",
|
||||
"サーバの起動状況を確認します。(4-2) \n",
|
||||
"\n",
|
||||
"このセルは繰り返し実行することになるのでCtrl+Retでセルを実行してください。\n",
|
||||
"\n",
|
||||
"下記のようなテキストが表示されたら起動完了です。\n",
|
||||
"\n",
|
||||
"**`DEBUG:asyncio:Using selector: EpollSelector`**\n",
|
||||
"\n",
|
||||
"```\n",
|
||||
" Voice Changerを起動しています。\n",
|
||||
" -- 設定 -- \n",
|
||||
" CONFIG:None, MODEL:None ONNX_MODEL:None\n",
|
||||
"```\n",
|
||||
"\n"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "-_2OcN9Borke"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"# (4-1) サーバの起動\n",
|
||||
"import random\n",
|
||||
"PORT = 10000 + random.randint(1, 9999)\n",
|
||||
"LOG_FILE = f\"LOG_FILE_{PORT}\"\n",
|
||||
"\n",
|
||||
"get_ipython().system_raw(f'python3 MMVCServerSIO.py -t MMVC -p {PORT} --https False --colab True >{LOG_FILE} 2>&1 &')\n",
|
||||
"#print(f\"PORT:{PORT}, LOG_FILE:{LOG_FILE}\")"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "G-nMdPxEW1rc"
|
||||
},
|
||||
"execution_count": 7,
|
||||
"outputs": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"# (4-2) サーバの起動確認\n",
|
||||
"!sleep 30\n",
|
||||
"!tail -20 {LOG_FILE}"
|
||||
],
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"base_uri": "https://localhost:8080/"
|
||||
},
|
||||
"id": "chu06KpAjEK6",
|
||||
"outputId": "b7e4b74e-2712-41a0-95ad-cfc6f65f5f7c"
|
||||
},
|
||||
"execution_count": 10,
|
||||
"outputs": [
|
||||
{
|
||||
"output_type": "stream",
|
||||
"name": "stdout",
|
||||
"text": [
|
||||
"\u001b[32m Voice Changerを起動しています。\u001b[0m\n",
|
||||
"\u001b[34m -- 設定 -- \u001b[0m\n",
|
||||
"\u001b[34m CONFIG:None, MODEL:None ONNX_MODEL:None\u001b[0m\n"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"# プロキシを起動\n",
|
||||
"ウェブサーバへのアクセスをするためのプロキシを起動します。\n",
|
||||
"\n",
|
||||
"表示されたURLをクリックして開くと別タブでアプリが開きます。\n",
|
||||
"\n",
|
||||
"Colabなので、ロードにある程度時間がかかります(30秒くらい)。"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "WhxcFLQEpctq"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"# (5) プロキシを起動\n",
|
||||
"from google.colab.output import eval_js\n",
|
||||
"proxy = eval_js( \"google.colab.kernel.proxyPort(\" + str(PORT) + \")\" )\n",
|
||||
"print(f\"{proxy}front/?colab=true\")"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "nkRjZm95l87C",
|
||||
"colab": {
|
||||
"base_uri": "https://localhost:8080/",
|
||||
"height": 34
|
||||
},
|
||||
"outputId": "0630d9ea-3dd4-422f-ebd0-a5930edb3b07"
|
||||
},
|
||||
"execution_count": 9,
|
||||
"outputs": [
|
||||
{
|
||||
"output_type": "stream",
|
||||
"name": "stdout",
|
||||
"text": [
|
||||
"https://1ipsaxpb34k-496ff2e9c6d22116-17980-colab.googleusercontent.com/front/?colab=true\n"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [],
|
||||
"metadata": {
|
||||
"id": "axkt5BjhoiPV"
|
||||
},
|
||||
"execution_count": 6,
|
||||
"outputs": []
|
||||
}
|
||||
]
|
||||
}
|
@ -1,656 +0,0 @@
|
||||
{
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 0,
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"provenance": [],
|
||||
"collapsed_sections": [],
|
||||
"authorship_tag": "ABX9TyP6Wv8fttT+X2Op6MmqB/kg",
|
||||
"include_colab_link": true
|
||||
},
|
||||
"kernelspec": {
|
||||
"name": "python3",
|
||||
"display_name": "Python 3"
|
||||
},
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
},
|
||||
"gpuClass": "standard"
|
||||
},
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "view-in-github",
|
||||
"colab_type": "text"
|
||||
},
|
||||
"source": [
|
||||
"<a href=\"https://colab.research.google.com/github/w-okada/voice-changer/blob/dev/VoiceRecorder.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"Voice Recorder\n",
|
||||
"---\n",
|
||||
"\n",
|
||||
"このノートでは、MMVCのトレーニング用の音声を録画するアプリ\"Voice Recorder\"をColab上から起動します。\n",
|
||||
"\n",
|
||||
"録音された音声はこのノートを通してGoogle Drive上にアップロードすることができます。\n",
|
||||
"\n",
|
||||
"また、従来のVoice Recorderと同様にローカルPCにダウンロードすることもできます。\n",
|
||||
"\n",
|
||||
"録音後にブラウザとcolab上のサーバ間でやり取りを行うので、更新に少しタイムラグが発生します。\n",
|
||||
"\n",
|
||||
"ご自身のPCでトレーニングを行う予定の場合は、colab上のサーバで録音するメリットはほぼありませんので、より快適な録音をするために[こちらのgithub上のVoice Recorder](https://w-okada.github.io/voice-changer/)をご使用ください。\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"より詳細な情報はこちらの[リポジトリ](https://github.com/w-okada/voice-changer)からご確認いただけます。\n"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "Lbbmx_Vjl0zo"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"# 録音データを格納するフォルダを指定\n",
|
||||
"\n",
|
||||
"フォルダは次の二つを指定する必要があります。\n",
|
||||
"1. 録音アプリ用のキャッシュデータ格納フォルダ\n",
|
||||
"2. トレーニングデータの格納フォルダ\n",
|
||||
"\n",
|
||||
"通常、録音データはGoogle Drive上のフォルダに格納すると思います。\n",
|
||||
"\n",
|
||||
"まずは(1-1)を実行してドライブをマウントしてください。\n",
|
||||
"\n",
|
||||
"その後、(1-2)で上記の格納フォルダを指定してください。"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "mHvGrgaWnIPA"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"# (1-1) Google Driveのマウント\n",
|
||||
"from google.colab import drive\n",
|
||||
"drive.mount('/content/drive')"
|
||||
],
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"base_uri": "https://localhost:8080/"
|
||||
},
|
||||
"id": "Eihm8H2X-7wm",
|
||||
"outputId": "76331fb1-5ef8-40e6-a381-258b5e425853"
|
||||
},
|
||||
"execution_count": 1,
|
||||
"outputs": [
|
||||
{
|
||||
"output_type": "stream",
|
||||
"name": "stdout",
|
||||
"text": [
|
||||
"Mounted at /content/drive\n"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"# (1-2) 使用するモデルとコンフィグファイルの指定\n",
|
||||
"RECORDER_DATA_DIR=\"/content/drive/MyDrive/VoiceChanger/voice_data\"\n",
|
||||
"MMVC_DATA_DIR=\"/content/drive/MyDrive/VoiceChanger/dataset\"\n"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "nSXATMWYb4Ik"
|
||||
},
|
||||
"execution_count": 2,
|
||||
"outputs": []
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"# リポジトリのクローン\n",
|
||||
"リポジトリをクローンします"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "sLBfykjBnjWc"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"# (2) リポジトリのクローン\n",
|
||||
"!git clone --depth 1 https://github.com/w-okada/voice-changer.git -b ver_1.0\n",
|
||||
"%cd voice-changer/docs/\n"
|
||||
],
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"base_uri": "https://localhost:8080/"
|
||||
},
|
||||
"id": "86wTFmqsNMnD",
|
||||
"outputId": "40471833-d720-41c9-f4a7-ac15fbf18e14"
|
||||
},
|
||||
"execution_count": 3,
|
||||
"outputs": [
|
||||
{
|
||||
"output_type": "stream",
|
||||
"name": "stdout",
|
||||
"text": [
|
||||
"Cloning into 'voice-changer'...\n",
|
||||
"remote: Enumerating objects: 81, done.\u001b[K\n",
|
||||
"remote: Counting objects: 100% (81/81), done.\u001b[K\n",
|
||||
"remote: Compressing objects: 100% (68/68), done.\u001b[K\n",
|
||||
"remote: Total 81 (delta 12), reused 53 (delta 5), pack-reused 0\u001b[K\n",
|
||||
"Unpacking objects: 100% (81/81), done.\n",
|
||||
"Note: checking out 'f8823cb7e2025f13227f5918408cceda224bf9f0'.\n",
|
||||
"\n",
|
||||
"You are in 'detached HEAD' state. You can look around, make experimental\n",
|
||||
"changes and commit them, and you can discard any commits you make in this\n",
|
||||
"state without impacting any branches by performing another checkout.\n",
|
||||
"\n",
|
||||
"If you want to create a new branch to retain commits you create, you may\n",
|
||||
"do so (now or later) by using -b with the checkout command again. Example:\n",
|
||||
"\n",
|
||||
" git checkout -b <new-branch-name>\n",
|
||||
"\n",
|
||||
"/content/voice-changer/docs\n"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"# ファイルの配置\n",
|
||||
"アプリケーションの挙動を記した設定ファイルをコピーします(3-1)。(3-2)はコピーした設定ファイルを表示しています。もしかしたらうまく動かないときに役立つかもしれません。"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "jmDY8W_fnuSi"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"# (3-1) 設定ファイルのコピー\n",
|
||||
"!cp ../template/setting_recorder_colab.json assets/setting.json"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "ow88ZaubluOJ"
|
||||
},
|
||||
"execution_count": 4,
|
||||
"outputs": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"# (3-2) 設定ファイルの内容確認\n",
|
||||
"\n",
|
||||
"!cat assets/setting.json"
|
||||
],
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"base_uri": "https://localhost:8080/"
|
||||
},
|
||||
"id": "rpWUobjlBCNF",
|
||||
"outputId": "285e0259-16af-4932-e78b-bec94f337e9c"
|
||||
},
|
||||
"execution_count": 5,
|
||||
"outputs": [
|
||||
{
|
||||
"output_type": "stream",
|
||||
"name": "stdout",
|
||||
"text": [
|
||||
"{\n",
|
||||
" \"app_title\": \"voice-recorder\",\n",
|
||||
" \"storage_type\":\"server\",\n",
|
||||
" \"use_mel_spectrogram\":true,\n",
|
||||
" \"text\": [\n",
|
||||
" {\n",
|
||||
" \"title\": \"ITA-emotion\",\n",
|
||||
" \"wavPrefix\": \"emotion\",\n",
|
||||
" \"file\": \"./assets/text/ITA_emotion_all.txt\",\n",
|
||||
" \"file_hira\": \"./assets/text/ITA_emotion_all_hira.txt\"\n",
|
||||
" },\n",
|
||||
" {\n",
|
||||
" \"title\": \"ITA-recitation\",\n",
|
||||
" \"wavPrefix\": \"recitation\",\n",
|
||||
" \"file\": \"./assets/text/ITA_recitation_all.txt\",\n",
|
||||
" \"file_hira\": \"./assets/text/ITA_recitation_all_hira.txt\"\n",
|
||||
" },\n",
|
||||
" {\n",
|
||||
" \"title\": \"wagahaiwa\",\n",
|
||||
" \"wavPrefix\": \"wagahaiwa\",\n",
|
||||
" \"file\": \"./assets/text/wagahaiwa.txt\",\n",
|
||||
" \"file_hira\": \"./assets/text/wagahaiwa_hira.txt\"\n",
|
||||
" }\n",
|
||||
" ]\n",
|
||||
"}\n"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"# モジュールのインストール\n",
|
||||
"\n",
|
||||
"必要なモジュールをインストールします。"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "8Na2PbLZSWgZ"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"# (4) 設定ファイルの確認\n",
|
||||
"!pip install flask\n",
|
||||
"!pip install flask_cors\n"
|
||||
],
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"base_uri": "https://localhost:8080/"
|
||||
},
|
||||
"id": "LwZAAuqxX7yY",
|
||||
"outputId": "ea2b3b39-d571-4d47-a38b-d0e657a335cd"
|
||||
},
|
||||
"execution_count": 6,
|
||||
"outputs": [
|
||||
{
|
||||
"output_type": "stream",
|
||||
"name": "stdout",
|
||||
"text": [
|
||||
"Looking in indexes: https://pypi.org/simple, https://us-python.pkg.dev/colab-wheels/public/simple/\n",
|
||||
"Requirement already satisfied: flask in /usr/local/lib/python3.7/dist-packages (1.1.4)\n",
|
||||
"Requirement already satisfied: Jinja2<3.0,>=2.10.1 in /usr/local/lib/python3.7/dist-packages (from flask) (2.11.3)\n",
|
||||
"Requirement already satisfied: Werkzeug<2.0,>=0.15 in /usr/local/lib/python3.7/dist-packages (from flask) (1.0.1)\n",
|
||||
"Requirement already satisfied: click<8.0,>=5.1 in /usr/local/lib/python3.7/dist-packages (from flask) (7.1.2)\n",
|
||||
"Requirement already satisfied: itsdangerous<2.0,>=0.24 in /usr/local/lib/python3.7/dist-packages (from flask) (1.1.0)\n",
|
||||
"Requirement already satisfied: MarkupSafe>=0.23 in /usr/local/lib/python3.7/dist-packages (from Jinja2<3.0,>=2.10.1->flask) (2.0.1)\n",
|
||||
"Looking in indexes: https://pypi.org/simple, https://us-python.pkg.dev/colab-wheels/public/simple/\n",
|
||||
"Collecting flask_cors\n",
|
||||
" Downloading Flask_Cors-3.0.10-py2.py3-none-any.whl (14 kB)\n",
|
||||
"Requirement already satisfied: Six in /usr/local/lib/python3.7/dist-packages (from flask_cors) (1.15.0)\n",
|
||||
"Requirement already satisfied: Flask>=0.9 in /usr/local/lib/python3.7/dist-packages (from flask_cors) (1.1.4)\n",
|
||||
"Requirement already satisfied: Werkzeug<2.0,>=0.15 in /usr/local/lib/python3.7/dist-packages (from Flask>=0.9->flask_cors) (1.0.1)\n",
|
||||
"Requirement already satisfied: itsdangerous<2.0,>=0.24 in /usr/local/lib/python3.7/dist-packages (from Flask>=0.9->flask_cors) (1.1.0)\n",
|
||||
"Requirement already satisfied: Jinja2<3.0,>=2.10.1 in /usr/local/lib/python3.7/dist-packages (from Flask>=0.9->flask_cors) (2.11.3)\n",
|
||||
"Requirement already satisfied: click<8.0,>=5.1 in /usr/local/lib/python3.7/dist-packages (from Flask>=0.9->flask_cors) (7.1.2)\n",
|
||||
"Requirement already satisfied: MarkupSafe>=0.23 in /usr/local/lib/python3.7/dist-packages (from Jinja2<3.0,>=2.10.1->Flask>=0.9->flask_cors) (2.0.1)\n",
|
||||
"Installing collected packages: flask-cors\n",
|
||||
"Successfully installed flask-cors-3.0.10\n"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"# サーバの起動\n",
|
||||
"\n",
|
||||
"サーバを起動します。(5-1) \n",
|
||||
"\n",
|
||||
"サーバの起動状況を確認します。(5-2) \n",
|
||||
"\n",
|
||||
"このセルは繰り返し実行することになるのでCtrl+Retでセルを実行してください。\n",
|
||||
"\n",
|
||||
"アクセスできるようになるまで、数秒かかります。\n",
|
||||
"\n",
|
||||
"下記のようなテキストが表示されたら起動完了です。\n",
|
||||
"\n",
|
||||
"```\n",
|
||||
"[2022-09-13 22:20:49,936] INFO in recorderServer: START APP\n",
|
||||
" * Serving Flask app \"recorderServer\" (lazy loading)\n",
|
||||
" * Environment: production\n",
|
||||
" WARNING: This is a development server. Do not use it in a production deployment.\n",
|
||||
" Use a production WSGI server instead.\n",
|
||||
" * Debug mode: on\n",
|
||||
"[2022-09-13 22:20:49,946] INFO in _internal: * Running on http://0.0.0.0:8018/ (Press CTRL+C to quit)\n",
|
||||
"[2022-09-13 22:20:49,947] INFO in _internal: * Restarting with stat\n",
|
||||
"[2022-09-13 22:20:50,166] INFO in recorderServer: START APP\n",
|
||||
"[2022-09-13 22:20:50,174] WARNING in _internal: * Debugger is active!\n",
|
||||
"[2022-09-13 22:20:50,200] INFO in _internal: * Debugger PIN: 334-166-753\n",
|
||||
"```\n",
|
||||
"\n"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "-_2OcN9Borke"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"# (5-1) サーバの起動\n",
|
||||
"PORT=8018\n",
|
||||
"get_ipython().system_raw(f'python3 recorderServer.py {PORT} {RECORDER_DATA_DIR} >foo 2>&1 &')"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "iNOAB7zISI6J"
|
||||
},
|
||||
"execution_count": 7,
|
||||
"outputs": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"# (5-2) サーバの起動確認 (Ctrl+Retで実行)\n",
|
||||
"!cat foo"
|
||||
],
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"base_uri": "https://localhost:8080/"
|
||||
},
|
||||
"id": "chu06KpAjEK6",
|
||||
"outputId": "6f5cbed9-65a7-4570-f58a-5447e402947c"
|
||||
},
|
||||
"execution_count": 10,
|
||||
"outputs": [
|
||||
{
|
||||
"output_type": "stream",
|
||||
"name": "stdout",
|
||||
"text": [
|
||||
"[2022-11-08 19:11:17,679] INFO in recorderServer: START APP\n",
|
||||
" * Serving Flask app \"recorderServer\" (lazy loading)\n",
|
||||
" * Environment: production\n",
|
||||
" WARNING: This is a development server. Do not use it in a production deployment.\n",
|
||||
" Use a production WSGI server instead.\n",
|
||||
" * Debug mode: on\n",
|
||||
"[2022-11-08 19:11:17,696] INFO in _internal: * Running on http://0.0.0.0:8018/ (Press CTRL+C to quit)\n",
|
||||
"[2022-11-08 19:11:17,697] INFO in _internal: * Restarting with stat\n",
|
||||
"[2022-11-08 19:11:17,893] INFO in recorderServer: START APP\n",
|
||||
"[2022-11-08 19:11:17,900] WARNING in _internal: * Debugger is active!\n",
|
||||
"[2022-11-08 19:11:17,930] INFO in _internal: * Debugger PIN: 225-344-519\n"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"# プロキシを起動\n",
|
||||
"ウェブサーバへのアクセスをするためのプロキシを起動します。\n",
|
||||
"\n",
|
||||
"表示されたURLをクリックして開くと別タブでアプリが開きます。\n",
|
||||
"\n",
|
||||
"Colabなので、ロードにある程度時間がかかります(30秒くらい)。"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "WhxcFLQEpctq"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"# (7) プロキシを起動\n",
|
||||
"from google.colab import output\n",
|
||||
"\n",
|
||||
"output.serve_kernel_port_as_window(PORT)"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "nkRjZm95l87C",
|
||||
"colab": {
|
||||
"base_uri": "https://localhost:8080/",
|
||||
"height": 34
|
||||
},
|
||||
"outputId": "7d2664b8-945c-4ee6-b49f-51f7f96cf388"
|
||||
},
|
||||
"execution_count": 11,
|
||||
"outputs": [
|
||||
{
|
||||
"output_type": "display_data",
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"<IPython.core.display.Javascript object>"
|
||||
],
|
||||
"application/javascript": [
|
||||
"(async (port, path, text, element) => {\n",
|
||||
" if (!google.colab.kernel.accessAllowed) {\n",
|
||||
" return;\n",
|
||||
" }\n",
|
||||
" element.appendChild(document.createTextNode(''));\n",
|
||||
" const url = await google.colab.kernel.proxyPort(port);\n",
|
||||
" const anchor = document.createElement('a');\n",
|
||||
" anchor.href = new URL(path, url).toString();\n",
|
||||
" anchor.target = '_blank';\n",
|
||||
" anchor.setAttribute('data-href', url + path);\n",
|
||||
" anchor.textContent = text;\n",
|
||||
" element.appendChild(anchor);\n",
|
||||
" })(8018, \"/\", \"https://localhost:8018/\", window.element)"
|
||||
]
|
||||
},
|
||||
"metadata": {}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"# トレーニング用データフォルダ\n",
|
||||
"\n",
|
||||
"以下、トレーニング用のフォルダを作成します。\n",
|
||||
"\n",
|
||||
"\n"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "ZGuYYN7oCSM4"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"corpus_id = \"14oXoQqLxRkP8NJK8qMYGee1_q2uEED1z\"\n",
|
||||
"\n",
|
||||
"data_setting = [\n",
|
||||
" [\"user\", \"\", \"\", \"00_myvoice\", \"107\"],\n",
|
||||
" [\"zundamon\", \"1h8Ajyvoig7Hl3LSSt2vYX0sUHX3JDF3R\", \"1205_zundamon\", \"01_target_zundamon\", \"100\"],\n",
|
||||
" [\"tsumugi\", \"14zE0F_5ZCQWXf6m6SUPF5Y3gpL6yb7zk\", \"344_tsumugi\", \"02_target_tsumugi\", \"103\"],\n",
|
||||
" [\"metan\", \"1iCrpzhqXm-0YdktOPM8M1pMtgQIDF3r4\", \"459_methane\", \"03_target_metan\", \"102\"],\n",
|
||||
" [\"sora\", \"1MXfMRG_sjbsaLihm7wEASG2PwuCponZF\", \"912_sora\", \"04_target_ksora\", \"101\"],\n",
|
||||
"]"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "3PhrmCD2LaCH"
|
||||
},
|
||||
"execution_count": null,
|
||||
"outputs": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"import os, glob\n",
|
||||
"\n",
|
||||
"os.makedirs(MMVC_DATA_DIR, exist_ok=True)\n",
|
||||
"speaker_list = os.path.join(MMVC_DATA_DIR, \"multi_speaker_correspondence.txt\")\n",
|
||||
"!echo \"00_myvoice|107\" > {speaker_list}\n",
|
||||
"!echo \"01_target_zundamon|100\" >> {speaker_list}\n",
|
||||
"!echo \"02_target_tsumugi|103\" >> {speaker_list}\n",
|
||||
"!echo \"03_target_metan|102\" >> {speaker_list}\n",
|
||||
"!echo \"04_target_ksora|101\" >> {speaker_list}\n",
|
||||
"\n",
|
||||
"!cat {speaker_list}\n",
|
||||
"\n"
|
||||
],
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"base_uri": "https://localhost:8080/"
|
||||
},
|
||||
"id": "f5l6ggSyACLs",
|
||||
"outputId": "4db3571a-46e6-4fd9-c560-628cf4af9284"
|
||||
},
|
||||
"execution_count": null,
|
||||
"outputs": [
|
||||
{
|
||||
"output_type": "stream",
|
||||
"name": "stdout",
|
||||
"text": [
|
||||
"00_myvoice|107\n",
|
||||
"01_target_zundamon|100\n",
|
||||
"02_target_tsumugi|103\n",
|
||||
"03_target_metan|102\n",
|
||||
"04_target_ksora|101\n"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"!rm -rf /content/drive/MyDrive/VoiceChanger/train_data/00_myvoice/wav/*"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "UEVb2GGZSesY"
|
||||
},
|
||||
"execution_count": null,
|
||||
"outputs": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"import gdown\n",
|
||||
"\n",
|
||||
"gdown.download(f'https://drive.google.com/uc?id={corpus_id}', f'ita_corpus.zip', quiet=False)\n",
|
||||
"!unzip -oq 'ita_corpus.zip'\n",
|
||||
"\n",
|
||||
"for chara in data_setting:\n",
|
||||
" chara_root_dir = os.path.join(MMVC_DATA_DIR, chara[3])\n",
|
||||
" os.makedirs(chara_root_dir, exist_ok=True)\n",
|
||||
" \n",
|
||||
" chara_text_dir = os.path.join(chara_root_dir, \"text\")\n",
|
||||
" os.makedirs(chara_text_dir, exist_ok=True)\n",
|
||||
" chara_wav_dir = os.path.join(chara_root_dir, \"wav\")\n",
|
||||
" os.makedirs(chara_wav_dir, exist_ok=True)\n",
|
||||
"\n",
|
||||
" if chara[0] != \"user\":\n",
|
||||
" gdown.download(f'https://drive.google.com/uc?id={chara[1]}', f'{chara[0]}.zip', quiet=False)\n",
|
||||
" !unzip -f '{chara[0]}.zip'\n",
|
||||
" !cp -rf {chara[2]}/* {chara_root_dir}/\n",
|
||||
"\n",
|
||||
" if chara[0] == \"user\":\n",
|
||||
" !cp MMVC向けITAコーパス文章ファイル_配布用/ITA_emotion_hira_100file/* {chara_text_dir}\n",
|
||||
" !cp MMVC向けITAコーパス文章ファイル_配布用/ITA_recitation_hira_324file/* {chara_text_dir}\n",
|
||||
"\n",
|
||||
" file_list = [os.path.abspath(p) for p in glob.glob(f\"{RECORDER_DATA_DIR}/*/*.zip\")]\n",
|
||||
" for f in list(file_list):\n",
|
||||
" # print(f)\n",
|
||||
" basename = os.path.basename(f)\n",
|
||||
" wavname = os.path.splitext(basename)[0] + \".wav\"\n",
|
||||
" full_path = os.path.join(chara_wav_dir, wavname)\n",
|
||||
" # print(basename, wavname, full_path)\n",
|
||||
" !unzip -oq {f} vf24kTrim.wav\n",
|
||||
" !cp vf24kTrim.wav {full_path}\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n"
|
||||
],
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"base_uri": "https://localhost:8080/"
|
||||
},
|
||||
"id": "L8UsVp3dDs4R",
|
||||
"outputId": "5d640caf-87b0-45a6-aa0c-76295e537f6a"
|
||||
},
|
||||
"execution_count": null,
|
||||
"outputs": [
|
||||
{
|
||||
"output_type": "stream",
|
||||
"name": "stderr",
|
||||
"text": [
|
||||
"Downloading...\n",
|
||||
"From: https://drive.google.com/uc?id=14oXoQqLxRkP8NJK8qMYGee1_q2uEED1z\n",
|
||||
"To: /content/voice-changer/docs/ita_corpus.zip\n",
|
||||
"100%|██████████| 1.20M/1.20M [00:00<00:00, 87.9MB/s]\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"output_type": "stream",
|
||||
"name": "stdout",
|
||||
"text": [
|
||||
"/content/drive/MyDrive/VoiceChanger/voice_data/ITA-emotion/emotion000.zip\n",
|
||||
"/content/drive/MyDrive/VoiceChanger/voice_data/ITA-emotion/emotion002.zip\n",
|
||||
"/content/drive/MyDrive/VoiceChanger/voice_data/ITA-emotion/emotion001.zip\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"output_type": "stream",
|
||||
"name": "stderr",
|
||||
"text": [
|
||||
"Downloading...\n",
|
||||
"From: https://drive.google.com/uc?id=1h8Ajyvoig7Hl3LSSt2vYX0sUHX3JDF3R\n",
|
||||
"To: /content/voice-changer/docs/zundamon.zip\n",
|
||||
"100%|██████████| 55.6M/55.6M [00:00<00:00, 251MB/s]\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"output_type": "stream",
|
||||
"name": "stdout",
|
||||
"text": [
|
||||
"Archive: zundamon.zip\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"output_type": "stream",
|
||||
"name": "stderr",
|
||||
"text": [
|
||||
"Downloading...\n",
|
||||
"From: https://drive.google.com/uc?id=14zE0F_5ZCQWXf6m6SUPF5Y3gpL6yb7zk\n",
|
||||
"To: /content/voice-changer/docs/tsumugi.zip\n",
|
||||
"100%|██████████| 73.0M/73.0M [00:00<00:00, 226MB/s]\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"output_type": "stream",
|
||||
"name": "stdout",
|
||||
"text": [
|
||||
"Archive: tsumugi.zip\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"output_type": "stream",
|
||||
"name": "stderr",
|
||||
"text": [
|
||||
"Downloading...\n",
|
||||
"From: https://drive.google.com/uc?id=1iCrpzhqXm-0YdktOPM8M1pMtgQIDF3r4\n",
|
||||
"To: /content/voice-changer/docs/metan.zip\n",
|
||||
"100%|██████████| 51.8M/51.8M [00:00<00:00, 219MB/s]\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"output_type": "stream",
|
||||
"name": "stdout",
|
||||
"text": [
|
||||
"Archive: metan.zip\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"output_type": "stream",
|
||||
"name": "stderr",
|
||||
"text": [
|
||||
"Downloading...\n",
|
||||
"From: https://drive.google.com/uc?id=1MXfMRG_sjbsaLihm7wEASG2PwuCponZF\n",
|
||||
"To: /content/voice-changer/docs/sora.zip\n",
|
||||
"100%|██████████| 70.2M/70.2M [00:00<00:00, 184MB/s]\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"output_type": "stream",
|
||||
"name": "stdout",
|
||||
"text": [
|
||||
"Archive: sora.zip\n"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [],
|
||||
"metadata": {
|
||||
"id": "yHmaXx31EOta"
|
||||
},
|
||||
"execution_count": null,
|
||||
"outputs": []
|
||||
}
|
||||
]
|
||||
}
|
11
client/.vscode/settings.json
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"workbench.colorCustomizations": {
|
||||
"tab.activeBackground": "#65952acc"
|
||||
},
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"prettier.printWidth": 1024,
|
||||
"prettier.tabWidth": 4,
|
||||
"files.associations": {
|
||||
"*.css": "postcss"
|
||||
}
|
||||
}
|
3
client/buildAllDemo.sh
Executable file
@ -0,0 +1,3 @@
|
||||
#!/bin/bash
|
||||
|
||||
cd demo && ncu -u && npm install && npm run build:prod && cd -
|
11
client/demo/.vscode/settings.json
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"workbench.colorCustomizations": {
|
||||
"tab.activeBackground": "#65952acc"
|
||||
},
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"prettier.printWidth": 1024,
|
||||
"prettier.tabWidth": 4,
|
||||
"files.associations": {
|
||||
"*.css": "postcss"
|
||||
}
|
||||
}
|
11
client/demo/build-voice-changer-js.sh
Normal file
@ -0,0 +1,11 @@
|
||||
# cd ~/git-work/voice-changer-js/lib/ ; npm run build:dev; cd -
|
||||
# rm -rf node_modules/@dannadori/voice-changer-js
|
||||
# mkdir -p node_modules/@dannadori/voice-changer-js/dist
|
||||
# cp -r ~/git-work/voice-changer-js/lib/package.json node_modules/@dannadori/voice-changer-js/
|
||||
# cp -r ~/git-work/voice-changer-js/lib/dist node_modules/@dannadori/voice-changer-js/
|
||||
|
||||
cd ~/git-work/voice-changer-js/lib/ ; npm run build:prod; cd -
|
||||
rm -rf node_modules/@dannadori/voice-changer-js
|
||||
mkdir -p node_modules/@dannadori/voice-changer-js/dist
|
||||
cp -r ~/git-work/voice-changer-js/lib/package.json node_modules/@dannadori/voice-changer-js/
|
||||
cp -r ~/git-work/voice-changer-js/lib/dist node_modules/@dannadori/voice-changer-js/
|
928
client/demo/dist/assets/beatrice/female-clickable.svg
vendored
Normal file
@ -0,0 +1,928 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:ns2="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink" width="100%" height="100%" viewBox="100 60 420 450" version="1.1">
|
||||
<metadata>
|
||||
<rdf:RDF>
|
||||
<ns2:Work>
|
||||
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:date>2023-11-19T11:21:56.358384</dc:date>
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:creator>
|
||||
<ns2:Agent>
|
||||
<dc:title>Matplotlib v3.7.1, https://matplotlib.org/</dc:title>
|
||||
</ns2:Agent>
|
||||
</dc:creator>
|
||||
</ns2:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs>
|
||||
<style type="text/css">
|
||||
* {
|
||||
stroke-linejoin: round;
|
||||
stroke-linecap: butt
|
||||
}
|
||||
</style>
|
||||
<style type="text/css">
|
||||
.beatrice-node-pointer {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.beatrice-node-pointer:hover {
|
||||
stroke: gray;
|
||||
}
|
||||
|
||||
.beatrice-node-pointer-selected {
|
||||
stroke: #ef6767c2;
|
||||
stroke-width: 3
|
||||
}
|
||||
|
||||
.beatrice-text-pointer {
|
||||
cursor: pointer;
|
||||
pointer-events: none
|
||||
}
|
||||
|
||||
.beatrice-text-pointer:hover {
|
||||
/* ホバー時のスタイルは既に設定されたスタイルと異なる特定の属性を変更することができます。 */
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<g id="figure_1">
|
||||
<g id="patch_1">
|
||||
<path d="M 0 576 L 576 576 L 576 0 L 0 0 z " style="fill: #ffffff" />
|
||||
</g>
|
||||
<g id="axes_1">
|
||||
<g id="LineCollection_1">
|
||||
<path d="M 403.96157 149.258085 L 366.630583 148.159991 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 396.547407 371.476481 L 372.120414 365.421971 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 396.547407 371.476481 L 416.760989 346.999139 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 396.547407 371.476481 L 404.238335 402.754731 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 258.035169 326.134244 L 298.859694 332.465911 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 167.453327 366.897955 L 203.987537 347.931194 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 436.352807 416.173738 L 404.238335 402.754731 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 391.514336 242.048236 L 417.560846 259.464346 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 391.514336 242.048236 L 355.734145 235.68791 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 391.514336 242.048236 L 424.070309 219.021704 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 205.541044 459.711101 L 230.303076 436.148139 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 160.44225 292.540336 L 167.396334 325.961848 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 345.679012 107.607273 L 366.630583 148.159991 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 325.345004 219.195921 L 355.734145 235.68791 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 325.345004 219.195921 L 297.530501 194.55124 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 363.075301 201.701937 L 355.734145 235.68791 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 363.075301 201.701937 L 341.462109 170.414842 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 366.630583 148.159991 L 341.462109 170.414842 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 167.396334 325.961848 L 203.987537 347.931194 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 262.111309 181.887977 L 297.530501 194.55124 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 189.293496 262.735141 L 222.122563 261.416721 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 277.95603 462.622539 L 293.230217 421.393405 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 333.932593 269.342364 L 301.9174 258.124913 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 333.932593 269.342364 L 355.734145 235.68791 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 334.666605 338.097578 L 320.07566 368.578481 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 203.987537 347.931194 L 242.811958 354.082183 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 288.059985 363.924972 L 320.07566 368.578481 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 288.059985 363.924972 L 276.198518 388.99868 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 288.059985 363.924972 L 298.859694 332.465911 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 288.059985 363.924972 L 242.811958 354.082183 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 276.198518 388.99868 L 293.230217 421.393405 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 293.230217 421.393405 L 309.530924 454.827332 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 293.230217 421.393405 L 260.004712 426.426278 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 423.853712 378.321354 L 404.238335 402.754731 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 205.214352 217.066163 L 222.122563 261.416721 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 154.047193 423.153273 L 193.933786 408.004355 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 298.859694 332.465911 L 277.79477 306.980241 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 277.79477 306.980241 L 282.261978 282.779534 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 260.004712 426.426278 L 230.303076 436.148139 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 260.004712 426.426278 L 228.689744 409.959215 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 260.004712 426.426278 L 261.506403 474.152727 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 301.9174 258.124913 L 282.261978 282.779534 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 254.897329 263.033159 L 282.261978 282.779534 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 254.897329 263.033159 L 222.122563 261.416721 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 321.267463 403.021207 L 320.07566 368.578481 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 345.750267 380.131711 L 320.07566 368.578481 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 345.750267 380.131711 L 372.120414 365.421971 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 345.750267 380.131711 L 351.226176 419.342667 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 404.238335 402.754731 L 400.607869 434.730447 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 193.933786 408.004355 L 230.303076 436.148139 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
</g>
|
||||
<g id="PathCollection_1">
|
||||
<defs>
|
||||
<path id="C0_0_b0ffb3bf4a"
|
||||
d="M 0 11.18034 C 2.965061 11.18034 5.80908 10.002309 7.905694 7.905694 C 10.002309 5.80908 11.18034 2.965061 11.18034 -0 C 11.18034 -2.965061 10.002309 -5.80908 7.905694 -7.905694 C 5.80908 -10.002309 2.965061 -11.18034 0 -11.18034 C -2.965061 -11.18034 -5.80908 -10.002309 -7.905694 -7.905694 C -10.002309 -5.80908 -11.18034 -2.965061 -11.18034 0 C -11.18034 2.965061 -10.002309 5.80908 -7.905694 7.905694 C -5.80908 10.002309 -2.965061 11.18034 0 11.18034 z " />
|
||||
</defs>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-0"
|
||||
onclick="(()=>{console.log('node 0')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="403.96157" y="149.258085" style="fill: #e7f5d2" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-1"
|
||||
onclick="(()=>{console.log('node 1')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="396.547407" y="371.476481" style="fill: #fbe8f2" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-2"
|
||||
onclick="(()=>{console.log('node 2')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="258.035169" y="326.134244" style="fill: #cfebaa" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-3"
|
||||
onclick="(()=>{console.log('node 3')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="167.453327" y="366.897955" style="fill: #f1f6e8" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-4"
|
||||
onclick="(()=>{console.log('node 4')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="436.352807" y="416.173738" style="fill: #e89ac6" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-5"
|
||||
onclick="(()=>{console.log('node 5')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="391.514336" y="242.048236" style="fill: #f3bcdd" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-6"
|
||||
onclick="(()=>{console.log('node 6')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="205.541044" y="459.711101" style="fill: #fbd9ec" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-7"
|
||||
onclick="(()=>{console.log('node 7')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="160.44225" y="292.540336" style="fill: #9ed067" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-8"
|
||||
onclick="(()=>{console.log('node 8')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="424.070309" y="219.021704" style="fill: #e1f3c7" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-9"
|
||||
onclick="(()=>{console.log('node 9')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="345.679012" y="107.607273" style="fill: #d0ecad" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-10"
|
||||
onclick="(()=>{console.log('node 10')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="325.345004" y="219.195921" style="fill: #eff6e4" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-11"
|
||||
onclick="(()=>{console.log('node 11')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="363.075301" y="201.701937" style="fill: #f9f0f5" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-12"
|
||||
onclick="(()=>{console.log('node 12')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="366.630583" y="148.159991" style="fill: #ebf6dc" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-13"
|
||||
onclick="(()=>{console.log('node 13')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="341.462109" y="170.414842" style="fill: #fad6ea" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-14"
|
||||
onclick="(()=>{console.log('node 14')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="167.396334" y="325.961848" style="fill: #f5f7f3" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-15"
|
||||
onclick="(()=>{console.log('node 15')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="262.111309" y="181.887977" style="fill: #e9f5d6" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-16"
|
||||
onclick="(()=>{console.log('node 16')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="189.293496" y="262.735141" style="fill: #fce5f1" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-17"
|
||||
onclick="(()=>{console.log('node 17')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="277.95603" y="462.622539" style="fill: #c4e699" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-18"
|
||||
onclick="(()=>{console.log('node 18')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="333.932593" y="269.342364" style="fill: #f8f4f6" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-19"
|
||||
onclick="(()=>{console.log('node 19')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="416.760989" y="346.999139" style="fill: #eef6e2" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-20"
|
||||
onclick="(()=>{console.log('node 20')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="334.666605" y="338.097578" style="fill: #f5f7f3" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-21"
|
||||
onclick="(()=>{console.log('node 21')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="203.987537" y="347.931194" style="fill: #edf6df" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-22"
|
||||
onclick="(()=>{console.log('node 22')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="288.059985" y="363.924972" style="fill: #ddf1c1" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-23"
|
||||
onclick="(()=>{console.log('node 23')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="276.198518" y="388.99868" style="fill: #f5f7f3" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-24"
|
||||
onclick="(()=>{console.log('node 24')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="293.230217" y="421.393405" style="fill: #f3f7ef" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-25"
|
||||
onclick="(()=>{console.log('node 25')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="423.853712" y="378.321354" style="fill: #edf6df" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-26"
|
||||
onclick="(()=>{console.log('node 26')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="205.214352" y="217.066163" style="fill: #e7f5d2" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-27"
|
||||
onclick="(()=>{console.log('node 27')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="242.811958" y="354.082183" style="fill: #d2ecb0" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-28"
|
||||
onclick="(()=>{console.log('node 28')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="154.047193" y="423.153273" style="fill: #e6f5d0" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-29"
|
||||
onclick="(()=>{console.log('node 29')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="298.859694" y="332.465911" style="fill: #ecf6de" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-30"
|
||||
onclick="(()=>{console.log('node 30')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="277.79477" y="306.980241" style="fill: #eaf5d9" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-31"
|
||||
onclick="(()=>{console.log('node 31')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="260.004712" y="426.426278" style="fill: #f9f1f5" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-32"
|
||||
onclick="(()=>{console.log('node 32')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="301.9174" y="258.124913" style="fill: #dbf0bf" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-33"
|
||||
onclick="(()=>{console.log('node 33')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="254.897329" y="263.033159" style="fill: #eff6e4" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-34"
|
||||
onclick="(()=>{console.log('node 34')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="321.267463" y="403.021207" style="fill: #d0ecad" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-35"
|
||||
onclick="(()=>{console.log('node 35')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="345.750267" y="380.131711" style="fill: #f9eef4" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-36"
|
||||
onclick="(()=>{console.log('node 36')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="404.238335" y="402.754731" style="fill: #f9eef4" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-37"
|
||||
onclick="(()=>{console.log('node 37')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="355.734145" y="235.68791" style="fill: #f9eef4" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-38"
|
||||
onclick="(()=>{console.log('node 38')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="193.933786" y="408.004355" style="fill: #f0f6e7" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-39"
|
||||
onclick="(()=>{console.log('node 39')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="297.530501" y="194.55124" style="fill: #f3f6ed" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-40"
|
||||
onclick="(()=>{console.log('node 40')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="320.07566" y="368.578481" style="fill: #dbf0bf" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-41"
|
||||
onclick="(()=>{console.log('node 41')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="228.689744" y="409.959215" style="fill: #f9eff4" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-42"
|
||||
onclick="(()=>{console.log('node 42')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="351.226176" y="419.342667" style="fill: #cfebaa" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-43"
|
||||
onclick="(()=>{console.log('node 43')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="372.120414" y="365.421971" style="fill: #f7f6f7" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-44"
|
||||
onclick="(()=>{console.log('node 44')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="230.303076" y="436.148139" style="fill: #f8cee6" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-45"
|
||||
onclick="(()=>{console.log('node 45')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="261.506403" y="474.152727" style="fill: #e6f5d0" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-46"
|
||||
onclick="(()=>{console.log('node 46')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="417.560846" y="259.464346" style="fill: #b7e085" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-47"
|
||||
onclick="(()=>{console.log('node 47')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="400.607869" y="434.730447" style="fill: #f8cee6" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-48"
|
||||
onclick="(()=>{console.log('node 48')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="282.261978" y="282.779534" style="fill: #d6eeb6" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-49"
|
||||
onclick="(()=>{console.log('node 49')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="222.122563" y="261.416721" style="fill: #edf6df" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-50"
|
||||
onclick="(()=>{console.log('node 50')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="309.530924" y="454.827332" style="fill: #f9eef4" />
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-0" onclick="(()=>{console.log('text 0 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(399.786883 152.569335) scale(0.12 -0.12)">
|
||||
<defs>
|
||||
<path id="DejaVuSans-Bold-32"
|
||||
d="M 1844 884 L 3897 884 L 3897 0 L 506 0 L 506 884 L 2209 2388 Q 2438 2594 2547 2791 Q 2656 2988 2656 3200 Q 2656 3528 2436 3728 Q 2216 3928 1850 3928 Q 1569 3928 1234 3808 Q 900 3688 519 3450 L 519 4475 Q 925 4609 1322 4679 Q 1719 4750 2100 4750 Q 2938 4750 3402 4381 Q 3866 4013 3866 3353 Q 3866 2972 3669 2642 Q 3472 2313 2841 1759 L 1844 884 z "
|
||||
transform="scale(0.015625)" />
|
||||
</defs>
|
||||
<use xlink:href="#DejaVuSans-Bold-32" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-1" onclick="(()=>{console.log('text 1 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(392.37272 374.787731) scale(0.12 -0.12)">
|
||||
<defs>
|
||||
<path id="DejaVuSans-Bold-34"
|
||||
d="M 2356 3675 L 1038 1722 L 2356 1722 L 2356 3675 z M 2156 4666 L 3494 4666 L 3494 1722 L 4159 1722 L 4159 850 L 3494 850 L 3494 0 L 2356 0 L 2356 850 L 288 850 L 288 1881 L 2156 4666 z "
|
||||
transform="scale(0.015625)" />
|
||||
</defs>
|
||||
<use xlink:href="#DejaVuSans-Bold-34" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-2" onclick="(()=>{console.log('text 2 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(253.860482 329.445494) scale(0.12 -0.12)">
|
||||
<defs>
|
||||
<path id="DejaVuSans-Bold-37"
|
||||
d="M 428 4666 L 3944 4666 L 3944 3988 L 2125 0 L 953 0 L 2675 3781 L 428 3781 L 428 4666 z "
|
||||
transform="scale(0.015625)" />
|
||||
</defs>
|
||||
<use xlink:href="#DejaVuSans-Bold-37" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-3" onclick="(()=>{console.log('text 3 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(163.27864 370.209205) scale(0.12 -0.12)">
|
||||
<defs>
|
||||
<path id="DejaVuSans-Bold-38"
|
||||
d="M 2228 2088 Q 1891 2088 1709 1903 Q 1528 1719 1528 1375 Q 1528 1031 1709 848 Q 1891 666 2228 666 Q 2563 666 2741 848 Q 2919 1031 2919 1375 Q 2919 1722 2741 1905 Q 2563 2088 2228 2088 z M 1350 2484 Q 925 2613 709 2878 Q 494 3144 494 3541 Q 494 4131 934 4440 Q 1375 4750 2228 4750 Q 3075 4750 3515 4442 Q 3956 4134 3956 3541 Q 3956 3144 3739 2878 Q 3522 2613 3097 2484 Q 3572 2353 3814 2058 Q 4056 1763 4056 1313 Q 4056 619 3595 264 Q 3134 -91 2228 -91 Q 1319 -91 855 264 Q 391 619 391 1313 Q 391 1763 633 2058 Q 875 2353 1350 2484 z M 1631 3419 Q 1631 3141 1786 2991 Q 1941 2841 2228 2841 Q 2509 2841 2662 2991 Q 2816 3141 2816 3419 Q 2816 3697 2662 3845 Q 2509 3994 2228 3994 Q 1941 3994 1786 3844 Q 1631 3694 1631 3419 z "
|
||||
transform="scale(0.015625)" />
|
||||
</defs>
|
||||
<use xlink:href="#DejaVuSans-Bold-38" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-4" onclick="(()=>{console.log('text 4 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(428.003432 419.484988) scale(0.12 -0.12)">
|
||||
<defs>
|
||||
<path id="DejaVuSans-Bold-31"
|
||||
d="M 750 831 L 1813 831 L 1813 3847 L 722 3622 L 722 4441 L 1806 4666 L 2950 4666 L 2950 831 L 4013 831 L 4013 0 L 750 0 L 750 831 z "
|
||||
transform="scale(0.015625)" />
|
||||
<path id="DejaVuSans-Bold-30"
|
||||
d="M 2944 2338 Q 2944 3213 2780 3570 Q 2616 3928 2228 3928 Q 1841 3928 1675 3570 Q 1509 3213 1509 2338 Q 1509 1453 1675 1090 Q 1841 728 2228 728 Q 2613 728 2778 1090 Q 2944 1453 2944 2338 z M 4147 2328 Q 4147 1169 3647 539 Q 3147 -91 2228 -91 Q 1306 -91 806 539 Q 306 1169 306 2328 Q 306 3491 806 4120 Q 1306 4750 2228 4750 Q 3147 4750 3647 4120 Q 4147 3491 4147 2328 z "
|
||||
transform="scale(0.015625)" />
|
||||
</defs>
|
||||
<use xlink:href="#DejaVuSans-Bold-31" />
|
||||
<use xlink:href="#DejaVuSans-Bold-30" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-5" onclick="(()=>{console.log('text 5 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(383.164961 245.359486) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-31" />
|
||||
<use xlink:href="#DejaVuSans-Bold-34" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-6" onclick="(()=>{console.log('text 6 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(197.191669 463.022351) scale(0.12 -0.12)">
|
||||
<defs>
|
||||
<path id="DejaVuSans-Bold-35"
|
||||
d="M 678 4666 L 3669 4666 L 3669 3781 L 1638 3781 L 1638 3059 Q 1775 3097 1914 3117 Q 2053 3138 2203 3138 Q 3056 3138 3531 2711 Q 4006 2284 4006 1522 Q 4006 766 3489 337 Q 2972 -91 2053 -91 Q 1656 -91 1267 -14 Q 878 63 494 219 L 494 1166 Q 875 947 1217 837 Q 1559 728 1863 728 Q 2300 728 2551 942 Q 2803 1156 2803 1522 Q 2803 1891 2551 2103 Q 2300 2316 1863 2316 Q 1603 2316 1309 2248 Q 1016 2181 678 2041 L 678 4666 z "
|
||||
transform="scale(0.015625)" />
|
||||
</defs>
|
||||
<use xlink:href="#DejaVuSans-Bold-31" />
|
||||
<use xlink:href="#DejaVuSans-Bold-35" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-7" onclick="(()=>{console.log('text 7 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(152.092875 295.851586) scale(0.12 -0.12)">
|
||||
<defs>
|
||||
<path id="DejaVuSans-Bold-36"
|
||||
d="M 2316 2303 Q 2000 2303 1842 2098 Q 1684 1894 1684 1484 Q 1684 1075 1842 870 Q 2000 666 2316 666 Q 2634 666 2792 870 Q 2950 1075 2950 1484 Q 2950 1894 2792 2098 Q 2634 2303 2316 2303 z M 3803 4544 L 3803 3681 Q 3506 3822 3243 3889 Q 2981 3956 2731 3956 Q 2194 3956 1894 3657 Q 1594 3359 1544 2772 Q 1750 2925 1990 3001 Q 2231 3078 2516 3078 Q 3231 3078 3670 2659 Q 4109 2241 4109 1563 Q 4109 813 3618 361 Q 3128 -91 2303 -91 Q 1394 -91 895 523 Q 397 1138 397 2266 Q 397 3422 980 4083 Q 1563 4744 2578 4744 Q 2900 4744 3203 4694 Q 3506 4644 3803 4544 z "
|
||||
transform="scale(0.015625)" />
|
||||
</defs>
|
||||
<use xlink:href="#DejaVuSans-Bold-31" />
|
||||
<use xlink:href="#DejaVuSans-Bold-36" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-8" onclick="(()=>{console.log('text 8 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(415.720934 222.332954) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-31" />
|
||||
<use xlink:href="#DejaVuSans-Bold-37" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-9" onclick="(()=>{console.log('text 9 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(337.329637 110.918523) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-31" />
|
||||
<use xlink:href="#DejaVuSans-Bold-38" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-10" onclick="(()=>{console.log('text 10 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(316.995629 222.507171) scale(0.12 -0.12)">
|
||||
<defs>
|
||||
<path id="DejaVuSans-Bold-39"
|
||||
d="M 641 103 L 641 966 Q 928 831 1190 764 Q 1453 697 1709 697 Q 2247 697 2547 995 Q 2847 1294 2900 1881 Q 2688 1725 2447 1647 Q 2206 1569 1925 1569 Q 1209 1569 770 1986 Q 331 2403 331 3084 Q 331 3838 820 4291 Q 1309 4744 2131 4744 Q 3044 4744 3544 4128 Q 4044 3513 4044 2388 Q 4044 1231 3459 570 Q 2875 -91 1856 -91 Q 1528 -91 1228 -42 Q 928 6 641 103 z M 2125 2350 Q 2441 2350 2600 2554 Q 2759 2759 2759 3169 Q 2759 3575 2600 3781 Q 2441 3988 2125 3988 Q 1809 3988 1650 3781 Q 1491 3575 1491 3169 Q 1491 2759 1650 2554 Q 1809 2350 2125 2350 z "
|
||||
transform="scale(0.015625)" />
|
||||
</defs>
|
||||
<use xlink:href="#DejaVuSans-Bold-31" />
|
||||
<use xlink:href="#DejaVuSans-Bold-39" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-11" onclick="(()=>{console.log('text 11 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(354.725926 205.013187) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-32" />
|
||||
<use xlink:href="#DejaVuSans-Bold-34" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-12" onclick="(()=>{console.log('text 12 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(358.281208 151.471241) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-32" />
|
||||
<use xlink:href="#DejaVuSans-Bold-35" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-13" onclick="(()=>{console.log('text 13 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(333.112734 173.726092) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-32" />
|
||||
<use xlink:href="#DejaVuSans-Bold-36" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-14" onclick="(()=>{console.log('text 14 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(159.046959 329.273098) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-32" />
|
||||
<use xlink:href="#DejaVuSans-Bold-37" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-15" onclick="(()=>{console.log('text 15 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(253.761934 185.199227) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-32" />
|
||||
<use xlink:href="#DejaVuSans-Bold-39" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-16" onclick="(()=>{console.log('text 16 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(180.944121 266.046391) scale(0.12 -0.12)">
|
||||
<defs>
|
||||
<path id="DejaVuSans-Bold-33"
|
||||
d="M 2981 2516 Q 3453 2394 3698 2092 Q 3944 1791 3944 1325 Q 3944 631 3412 270 Q 2881 -91 1863 -91 Q 1503 -91 1142 -33 Q 781 25 428 141 L 428 1069 Q 766 900 1098 814 Q 1431 728 1753 728 Q 2231 728 2486 893 Q 2741 1059 2741 1369 Q 2741 1688 2480 1852 Q 2219 2016 1709 2016 L 1228 2016 L 1228 2791 L 1734 2791 Q 2188 2791 2409 2933 Q 2631 3075 2631 3366 Q 2631 3634 2415 3781 Q 2200 3928 1806 3928 Q 1516 3928 1219 3862 Q 922 3797 628 3669 L 628 4550 Q 984 4650 1334 4700 Q 1684 4750 2022 4750 Q 2931 4750 3382 4451 Q 3834 4153 3834 3553 Q 3834 3144 3618 2883 Q 3403 2622 2981 2516 z "
|
||||
transform="scale(0.015625)" />
|
||||
</defs>
|
||||
<use xlink:href="#DejaVuSans-Bold-33" />
|
||||
<use xlink:href="#DejaVuSans-Bold-30" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-17" onclick="(()=>{console.log('text 17 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(269.606655 465.933789) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-33" />
|
||||
<use xlink:href="#DejaVuSans-Bold-35" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-18" onclick="(()=>{console.log('text 18 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(325.583218 272.653614) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-33" />
|
||||
<use xlink:href="#DejaVuSans-Bold-36" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-19" onclick="(()=>{console.log('text 19 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(408.411614 350.310389) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-33" />
|
||||
<use xlink:href="#DejaVuSans-Bold-38" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-20" onclick="(()=>{console.log('text 20 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(326.31723 341.408828) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-33" />
|
||||
<use xlink:href="#DejaVuSans-Bold-39" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-21" onclick="(()=>{console.log('text 21 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(195.638162 351.242444) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-34" />
|
||||
<use xlink:href="#DejaVuSans-Bold-30" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-22" onclick="(()=>{console.log('text 22 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(279.71061 367.236222) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-34" />
|
||||
<use xlink:href="#DejaVuSans-Bold-33" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-23" onclick="(()=>{console.log('text 23 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(267.849143 392.30993) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-35" />
|
||||
<use xlink:href="#DejaVuSans-Bold-31" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-24" onclick="(()=>{console.log('text 24 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(284.880842 424.704655) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-35" />
|
||||
<use xlink:href="#DejaVuSans-Bold-33" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-25" onclick="(()=>{console.log('text 25 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(415.504337 381.632604) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-35" />
|
||||
<use xlink:href="#DejaVuSans-Bold-35" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-26" onclick="(()=>{console.log('text 26 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(196.864977 220.377413) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-35" />
|
||||
<use xlink:href="#DejaVuSans-Bold-36" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-27" onclick="(()=>{console.log('text 27 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(234.462583 357.393433) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-35" />
|
||||
<use xlink:href="#DejaVuSans-Bold-37" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-28" onclick="(()=>{console.log('text 28 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(145.697818 426.464523) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-35" />
|
||||
<use xlink:href="#DejaVuSans-Bold-38" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-29" onclick="(()=>{console.log('text 29 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(290.510319 335.777161) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-35" />
|
||||
<use xlink:href="#DejaVuSans-Bold-39" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-30" onclick="(()=>{console.log('text 30 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(269.445395 310.291491) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-36" />
|
||||
<use xlink:href="#DejaVuSans-Bold-30" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-31" onclick="(()=>{console.log('text 31 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(251.655337 429.737528) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-36" />
|
||||
<use xlink:href="#DejaVuSans-Bold-31" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-32" onclick="(()=>{console.log('text 32 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(293.568025 261.436163) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-36" />
|
||||
<use xlink:href="#DejaVuSans-Bold-32" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-33" onclick="(()=>{console.log('text 33 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(246.547954 266.344409) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-36" />
|
||||
<use xlink:href="#DejaVuSans-Bold-33" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-34" onclick="(()=>{console.log('text 34 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(312.918088 406.332457) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-36" />
|
||||
<use xlink:href="#DejaVuSans-Bold-34" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-35" onclick="(()=>{console.log('text 35 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(337.400892 383.442961) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-36" />
|
||||
<use xlink:href="#DejaVuSans-Bold-35" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-36" onclick="(()=>{console.log('text 36 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(395.88896 406.065981) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-36" />
|
||||
<use xlink:href="#DejaVuSans-Bold-36" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-37" onclick="(()=>{console.log('text 37 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(347.38477 238.99916) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-36" />
|
||||
<use xlink:href="#DejaVuSans-Bold-37" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-38" onclick="(()=>{console.log('text 38 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(185.584411 411.315605) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-36" />
|
||||
<use xlink:href="#DejaVuSans-Bold-39" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-39" onclick="(()=>{console.log('text 39 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(289.181126 197.86249) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-37" />
|
||||
<use xlink:href="#DejaVuSans-Bold-32" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-40" onclick="(()=>{console.log('text 40 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(311.726285 371.889731) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-38" />
|
||||
<use xlink:href="#DejaVuSans-Bold-32" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-41" onclick="(()=>{console.log('text 41 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(220.340369 413.270465) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-38" />
|
||||
<use xlink:href="#DejaVuSans-Bold-33" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-42" onclick="(()=>{console.log('text 42 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(342.876801 422.653917) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-38" />
|
||||
<use xlink:href="#DejaVuSans-Bold-34" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-43" onclick="(()=>{console.log('text 43 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(363.771039 368.733221) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-38" />
|
||||
<use xlink:href="#DejaVuSans-Bold-35" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-44" onclick="(()=>{console.log('text 44 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(221.953701 439.459389) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-39" />
|
||||
<use xlink:href="#DejaVuSans-Bold-30" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-45" onclick="(()=>{console.log('text 45 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(253.157028 477.463977) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-39" />
|
||||
<use xlink:href="#DejaVuSans-Bold-31" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-46" onclick="(()=>{console.log('text 46 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(409.211471 262.775596) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-39" />
|
||||
<use xlink:href="#DejaVuSans-Bold-32" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-47" onclick="(()=>{console.log('text 47 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(392.258494 438.041697) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-39" />
|
||||
<use xlink:href="#DejaVuSans-Bold-33" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-48" onclick="(()=>{console.log('text 48 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(273.912603 286.090784) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-39" />
|
||||
<use xlink:href="#DejaVuSans-Bold-34" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-49" onclick="(()=>{console.log('text 49 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(213.773188 264.727971) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-39" />
|
||||
<use xlink:href="#DejaVuSans-Bold-35" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-50" onclick="(()=>{console.log('text 50 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(301.181549 458.138582) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-39" />
|
||||
<use xlink:href="#DejaVuSans-Bold-36" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="pe3de578e26">
|
||||
<rect x="124.405104" y="69.12" width="341.589792" height="443.52" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 56 KiB |
898
client/demo/dist/assets/beatrice/male-clickable.svg
vendored
Normal file
@ -0,0 +1,898 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:ns2="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink" width="100%" height="100%" viewBox="100 60 420 450" version="1.1">
|
||||
<metadata>
|
||||
<rdf:RDF>
|
||||
<ns2:Work>
|
||||
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:date>2023-11-19T11:21:55.705408</dc:date>
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:creator>
|
||||
<ns2:Agent>
|
||||
<dc:title>Matplotlib v3.7.1, https://matplotlib.org/</dc:title>
|
||||
</ns2:Agent>
|
||||
</dc:creator>
|
||||
</ns2:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs>
|
||||
<style type="text/css">
|
||||
* {
|
||||
stroke-linejoin: round;
|
||||
stroke-linecap: butt
|
||||
}
|
||||
</style>
|
||||
<style type="text/css">
|
||||
.beatrice-node-pointer {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.beatrice-node-pointer:hover {
|
||||
stroke: gray;
|
||||
}
|
||||
|
||||
.beatrice-node-pointer-selected {
|
||||
stroke: #ef6767c2;
|
||||
stroke-width: 3
|
||||
}
|
||||
|
||||
.beatrice-text-pointer {
|
||||
cursor: pointer;
|
||||
pointer-events: none
|
||||
}
|
||||
|
||||
.beatrice-text-pointer:hover {
|
||||
/* ホバー時のスタイルは既に設定されたスタイルと異なる特定の属性を変更することができます。 */
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<g id="figure_1">
|
||||
<g id="patch_1">
|
||||
<path d="M 0 576 L 576 576 L 576 0 L 0 0 z " style="fill: #ffffff" />
|
||||
</g>
|
||||
<g id="axes_1">
|
||||
<g id="LineCollection_1">
|
||||
<path d="M 383.475478 335.382791 L 350.123561 336.312105 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 383.475478 335.382791 L 393.562573 295.917472 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 383.475478 335.382791 L 396.396073 371.656412 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 395.592267 184.349842 L 344.302973 166.290216 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 166.614267 246.553188 L 214.405523 244.575019 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 362.886037 395.352171 L 389.299516 416.267064 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 362.886037 395.352171 L 367.134249 434.454954 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 362.886037 395.352171 L 396.396073 371.656412 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 362.886037 395.352171 L 321.091057 403.95329 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 291.699254 114.456198 L 287.429936 148.935339 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 309.72476 346.813492 L 326.464644 303.679747 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 396.396073 371.656412 L 422.276969 403.842356 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 396.396073 371.656412 L 419.504487 334.14189 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 311.713 188.802087 L 278.840744 190.572938 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 311.713 188.802087 L 287.429936 148.935339 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 311.713 188.802087 L 344.302973 166.290216 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 213.805036 285.720019 L 216.196468 317.113868 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 213.805036 285.720019 L 241.321249 255.242558 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 213.805036 285.720019 L 169.41455 268.66905 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 326.464644 303.679747 L 341.073251 272.287852 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 326.464644 303.679747 L 281.878613 277.846944 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 326.464644 303.679747 L 350.123561 336.312105 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 468.104517 290.196764 L 453.314054 329.209099 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 252.522958 107.607273 L 287.429936 148.935339 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 241.817 158.353487 L 278.840744 190.572938 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 278.840744 190.572938 L 264.569363 223.030096 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 190.32114 223.314542 L 214.405523 244.575019 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 233.41271 348.401671 L 216.196468 317.113868 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 122.295483 352.502553 L 162.445269 355.484449 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 158.624602 400.46174 L 162.445269 355.484449 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 214.405523 244.575019 L 241.321249 255.242558 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 214.405523 244.575019 L 207.563253 203.013335 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 264.569363 223.030096 L 298.808991 236.296491 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 264.569363 223.030096 L 241.321249 255.242558 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 264.569363 223.030096 L 236.649711 206.251683 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 220.79649 394.869471 L 213.931911 434.927829 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 220.79649 394.869471 L 208.453065 361.465389 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 241.321249 255.242558 L 281.878613 277.846944 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 257.120877 296.156882 L 281.878613 277.846944 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 453.314054 329.209099 L 419.504487 334.14189 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 287.180764 309.56402 L 281.878613 277.846944 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 287.429936 148.935339 L 321.071206 134.027026 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 300.632415 433.812968 L 321.091057 403.95329 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 216.196468 317.113868 L 181.944484 318.835753 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 216.196468 317.113868 L 208.453065 361.465389 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 419.504487 334.14189 L 436.061109 363.566053 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 366.514998 474.152727 L 367.134249 434.454954 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 208.453065 361.465389 L 162.445269 355.484449 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
</g>
|
||||
<g id="PathCollection_1">
|
||||
<defs>
|
||||
<path id="C0_0_3858269516"
|
||||
d="M 0 11.18034 C 2.965061 11.18034 5.80908 10.002309 7.905694 7.905694 C 10.002309 5.80908 11.18034 2.965061 11.18034 -0 C 11.18034 -2.965061 10.002309 -5.80908 7.905694 -7.905694 C 5.80908 -10.002309 2.965061 -11.18034 0 -11.18034 C -2.965061 -11.18034 -5.80908 -10.002309 -7.905694 -7.905694 C -10.002309 -5.80908 -11.18034 -2.965061 -11.18034 0 C -11.18034 2.965061 -10.002309 5.80908 -7.905694 7.905694 C -5.80908 10.002309 -2.965061 11.18034 0 11.18034 z " />
|
||||
</defs>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-0" onclick="(()=>{console.log('node 0')})()"
|
||||
class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="383.475478" y="335.382791" style="fill: #fde2bb" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-1" onclick="(()=>{console.log('node 1')})()"
|
||||
class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="393.562573" y="295.917472" style="fill: #fdba68" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-2" onclick="(()=>{console.log('node 2')})()"
|
||||
class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="395.592267" y="184.349842" style="fill: #fbe9cf" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-3" onclick="(()=>{console.log('node 3')})()"
|
||||
class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="166.614267" y="246.553188" style="fill: #7e70ab" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-4" onclick="(()=>{console.log('node 4')})()"
|
||||
class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="362.886037" y="395.352171" style="fill: #e8e9f1" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-5" onclick="(()=>{console.log('node 5')})()"
|
||||
class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="291.699254" y="114.456198" style="fill: #f9b158" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-6" onclick="(()=>{console.log('node 6')})()"
|
||||
class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="309.72476" y="346.813492" style="fill: #e4e5f0" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-7" onclick="(()=>{console.log('node 7')})()"
|
||||
class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="396.396073" y="371.656412" style="fill: #fdcc8c" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-8" onclick="(()=>{console.log('node 8')})()"
|
||||
class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="311.713" y="188.802087" style="fill: #fedeb3" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-9" onclick="(()=>{console.log('node 9')})()"
|
||||
class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="213.805036" y="285.720019" style="fill: #bab5d7" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-10"
|
||||
onclick="(()=>{console.log('node 10')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="326.464644" y="303.679747" style="fill: #eaebf2" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-11"
|
||||
onclick="(()=>{console.log('node 11')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="468.104517" y="290.196764" style="fill: #f7f7f6" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-12"
|
||||
onclick="(()=>{console.log('node 12')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="169.41455" y="268.66905" style="fill: #dfe1ee" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-13"
|
||||
onclick="(()=>{console.log('node 13')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="252.522958" y="107.607273" style="fill: #eff0f4" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-14"
|
||||
onclick="(()=>{console.log('node 14')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="241.817" y="158.353487" style="fill: #e58a20" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-15"
|
||||
onclick="(()=>{console.log('node 15')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="278.840744" y="190.572938" style="fill: #fedbac" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-16"
|
||||
onclick="(()=>{console.log('node 16')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="190.32114" y="223.314542" style="fill: #dfe1ee" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-17"
|
||||
onclick="(()=>{console.log('node 17')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="233.41271" y="348.401671" style="fill: #c3c0dd" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-18"
|
||||
onclick="(()=>{console.log('node 18')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="122.295483" y="352.502553" style="fill: #fed8a6" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-19"
|
||||
onclick="(()=>{console.log('node 19')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="158.624602" y="400.46174" style="fill: #f7f6f3" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-20"
|
||||
onclick="(()=>{console.log('node 20')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="214.405523" y="244.575019" style="fill: #f9f2e9" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-21"
|
||||
onclick="(()=>{console.log('node 21')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="264.569363" y="223.030096" style="fill: #faecd7" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-22"
|
||||
onclick="(()=>{console.log('node 22')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="220.79649" y="394.869471" style="fill: #fbead2" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-23"
|
||||
onclick="(()=>{console.log('node 23')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="344.302973" y="166.290216" style="fill: #feddaf" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-24"
|
||||
onclick="(()=>{console.log('node 24')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="241.321249" y="255.242558" style="fill: #c3c0dd" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-25"
|
||||
onclick="(()=>{console.log('node 25')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="257.120877" y="296.156882" style="fill: #f9f0e4" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-26"
|
||||
onclick="(()=>{console.log('node 26')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="207.563253" y="203.013335" style="fill: #fbebd5" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-27"
|
||||
onclick="(()=>{console.log('node 27')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="453.314054" y="329.209099" style="fill: #fdc47b" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-28"
|
||||
onclick="(()=>{console.log('node 28')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="350.123561" y="336.312105" style="fill: #fbe9cf" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-29"
|
||||
onclick="(()=>{console.log('node 29')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="287.180764" y="309.56402" style="fill: #f7f6f3" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-30"
|
||||
onclick="(()=>{console.log('node 30')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="287.429936" y="148.935339" style="fill: #fbebd5" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-31"
|
||||
onclick="(()=>{console.log('node 31')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="281.878613" y="277.846944" style="fill: #d1d1e6" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-32"
|
||||
onclick="(()=>{console.log('node 32')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="300.632415" y="433.812968" style="fill: #fde2bb" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-33"
|
||||
onclick="(()=>{console.log('node 33')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="216.196468" y="317.113868" style="fill: #dddfed" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-34"
|
||||
onclick="(()=>{console.log('node 34')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="419.504487" y="334.14189" style="fill: #fdc57f" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-35"
|
||||
onclick="(()=>{console.log('node 35')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="321.071206" y="134.027026" style="fill: #fee0b6" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-36"
|
||||
onclick="(()=>{console.log('node 36')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="366.514998" y="474.152727" style="fill: #fdbd6e" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-37"
|
||||
onclick="(()=>{console.log('node 37')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="208.453065" y="361.465389" style="fill: #cccbe3" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-38"
|
||||
onclick="(()=>{console.log('node 38')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="236.649711" y="206.251683" style="fill: #faecd7" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-39"
|
||||
onclick="(()=>{console.log('node 39')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="298.808991" y="236.296491" style="fill: #fdc57f" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-40"
|
||||
onclick="(()=>{console.log('node 40')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="181.944484" y="318.835753" style="fill: #f9f0e4" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-41"
|
||||
onclick="(()=>{console.log('node 41')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="367.134249" y="434.454954" style="fill: #f6f6f7" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-42"
|
||||
onclick="(()=>{console.log('node 42')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="422.276969" y="403.842356" style="fill: #fdbf72" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-43"
|
||||
onclick="(()=>{console.log('node 43')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="321.091057" y="403.95329" style="fill: #f8f5f1" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-44"
|
||||
onclick="(()=>{console.log('node 44')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="162.445269" y="355.484449" style="fill: #eaebf2" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-45"
|
||||
onclick="(()=>{console.log('node 45')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="341.073251" y="272.287852" style="fill: #f6aa4f" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-46"
|
||||
onclick="(()=>{console.log('node 46')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="389.299516" y="416.267064" style="fill: #de8013" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-47"
|
||||
onclick="(()=>{console.log('node 47')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="213.931911" y="434.927829" style="fill: #fbb55e" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-48"
|
||||
onclick="(()=>{console.log('node 48')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="436.061109" y="363.566053" style="fill: #ebecf3" />
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-0" onclick="(()=>{console.log('text 0 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(379.30079 338.694041) scale(0.12 -0.12)">
|
||||
<defs>
|
||||
<path id="DejaVuSans-Bold-31"
|
||||
d="M 750 831 L 1813 831 L 1813 3847 L 722 3622 L 722 4441 L 1806 4666 L 2950 4666 L 2950 831 L 4013 831 L 4013 0 L 750 0 L 750 831 z "
|
||||
transform="scale(0.015625)" />
|
||||
</defs>
|
||||
<use xlink:href="#DejaVuSans-Bold-31" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-1" onclick="(()=>{console.log('text 1 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(389.387885 299.228722) scale(0.12 -0.12)">
|
||||
<defs>
|
||||
<path id="DejaVuSans-Bold-33"
|
||||
d="M 2981 2516 Q 3453 2394 3698 2092 Q 3944 1791 3944 1325 Q 3944 631 3412 270 Q 2881 -91 1863 -91 Q 1503 -91 1142 -33 Q 781 25 428 141 L 428 1069 Q 766 900 1098 814 Q 1431 728 1753 728 Q 2231 728 2486 893 Q 2741 1059 2741 1369 Q 2741 1688 2480 1852 Q 2219 2016 1709 2016 L 1228 2016 L 1228 2791 L 1734 2791 Q 2188 2791 2409 2933 Q 2631 3075 2631 3366 Q 2631 3634 2415 3781 Q 2200 3928 1806 3928 Q 1516 3928 1219 3862 Q 922 3797 628 3669 L 628 4550 Q 984 4650 1334 4700 Q 1684 4750 2022 4750 Q 2931 4750 3382 4451 Q 3834 4153 3834 3553 Q 3834 3144 3618 2883 Q 3403 2622 2981 2516 z "
|
||||
transform="scale(0.015625)" />
|
||||
</defs>
|
||||
<use xlink:href="#DejaVuSans-Bold-33" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-2" onclick="(()=>{console.log('text 2 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(391.41758 187.661092) scale(0.12 -0.12)">
|
||||
<defs>
|
||||
<path id="DejaVuSans-Bold-35"
|
||||
d="M 678 4666 L 3669 4666 L 3669 3781 L 1638 3781 L 1638 3059 Q 1775 3097 1914 3117 Q 2053 3138 2203 3138 Q 3056 3138 3531 2711 Q 4006 2284 4006 1522 Q 4006 766 3489 337 Q 2972 -91 2053 -91 Q 1656 -91 1267 -14 Q 878 63 494 219 L 494 1166 Q 875 947 1217 837 Q 1559 728 1863 728 Q 2300 728 2551 942 Q 2803 1156 2803 1522 Q 2803 1891 2551 2103 Q 2300 2316 1863 2316 Q 1603 2316 1309 2248 Q 1016 2181 678 2041 L 678 4666 z "
|
||||
transform="scale(0.015625)" />
|
||||
</defs>
|
||||
<use xlink:href="#DejaVuSans-Bold-35" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-3" onclick="(()=>{console.log('text 3 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(162.43958 249.864438) scale(0.12 -0.12)">
|
||||
<defs>
|
||||
<path id="DejaVuSans-Bold-36"
|
||||
d="M 2316 2303 Q 2000 2303 1842 2098 Q 1684 1894 1684 1484 Q 1684 1075 1842 870 Q 2000 666 2316 666 Q 2634 666 2792 870 Q 2950 1075 2950 1484 Q 2950 1894 2792 2098 Q 2634 2303 2316 2303 z M 3803 4544 L 3803 3681 Q 3506 3822 3243 3889 Q 2981 3956 2731 3956 Q 2194 3956 1894 3657 Q 1594 3359 1544 2772 Q 1750 2925 1990 3001 Q 2231 3078 2516 3078 Q 3231 3078 3670 2659 Q 4109 2241 4109 1563 Q 4109 813 3618 361 Q 3128 -91 2303 -91 Q 1394 -91 895 523 Q 397 1138 397 2266 Q 397 3422 980 4083 Q 1563 4744 2578 4744 Q 2900 4744 3203 4694 Q 3506 4644 3803 4544 z "
|
||||
transform="scale(0.015625)" />
|
||||
</defs>
|
||||
<use xlink:href="#DejaVuSans-Bold-36" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-4" onclick="(()=>{console.log('text 4 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(358.71135 398.663421) scale(0.12 -0.12)">
|
||||
<defs>
|
||||
<path id="DejaVuSans-Bold-39"
|
||||
d="M 641 103 L 641 966 Q 928 831 1190 764 Q 1453 697 1709 697 Q 2247 697 2547 995 Q 2847 1294 2900 1881 Q 2688 1725 2447 1647 Q 2206 1569 1925 1569 Q 1209 1569 770 1986 Q 331 2403 331 3084 Q 331 3838 820 4291 Q 1309 4744 2131 4744 Q 3044 4744 3544 4128 Q 4044 3513 4044 2388 Q 4044 1231 3459 570 Q 2875 -91 1856 -91 Q 1528 -91 1228 -42 Q 928 6 641 103 z M 2125 2350 Q 2441 2350 2600 2554 Q 2759 2759 2759 3169 Q 2759 3575 2600 3781 Q 2441 3988 2125 3988 Q 1809 3988 1650 3781 Q 1491 3575 1491 3169 Q 1491 2759 1650 2554 Q 1809 2350 2125 2350 z "
|
||||
transform="scale(0.015625)" />
|
||||
</defs>
|
||||
<use xlink:href="#DejaVuSans-Bold-39" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-5" onclick="(()=>{console.log('text 5 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(283.349879 117.767448) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-31" />
|
||||
<use xlink:href="#DejaVuSans-Bold-31" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-6" onclick="(()=>{console.log('text 6 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(301.375385 350.124742) scale(0.12 -0.12)">
|
||||
<defs>
|
||||
<path id="DejaVuSans-Bold-32"
|
||||
d="M 1844 884 L 3897 884 L 3897 0 L 506 0 L 506 884 L 2209 2388 Q 2438 2594 2547 2791 Q 2656 2988 2656 3200 Q 2656 3528 2436 3728 Q 2216 3928 1850 3928 Q 1569 3928 1234 3808 Q 900 3688 519 3450 L 519 4475 Q 925 4609 1322 4679 Q 1719 4750 2100 4750 Q 2938 4750 3402 4381 Q 3866 4013 3866 3353 Q 3866 2972 3669 2642 Q 3472 2313 2841 1759 L 1844 884 z "
|
||||
transform="scale(0.015625)" />
|
||||
</defs>
|
||||
<use xlink:href="#DejaVuSans-Bold-31" />
|
||||
<use xlink:href="#DejaVuSans-Bold-32" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-7" onclick="(()=>{console.log('text 7 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(388.046698 374.967662) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-31" />
|
||||
<use xlink:href="#DejaVuSans-Bold-33" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-8" onclick="(()=>{console.log('text 8 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(303.363625 192.113337) scale(0.12 -0.12)">
|
||||
<defs>
|
||||
<path id="DejaVuSans-Bold-30"
|
||||
d="M 2944 2338 Q 2944 3213 2780 3570 Q 2616 3928 2228 3928 Q 1841 3928 1675 3570 Q 1509 3213 1509 2338 Q 1509 1453 1675 1090 Q 1841 728 2228 728 Q 2613 728 2778 1090 Q 2944 1453 2944 2338 z M 4147 2328 Q 4147 1169 3647 539 Q 3147 -91 2228 -91 Q 1306 -91 806 539 Q 306 1169 306 2328 Q 306 3491 806 4120 Q 1306 4750 2228 4750 Q 3147 4750 3647 4120 Q 4147 3491 4147 2328 z "
|
||||
transform="scale(0.015625)" />
|
||||
</defs>
|
||||
<use xlink:href="#DejaVuSans-Bold-32" />
|
||||
<use xlink:href="#DejaVuSans-Bold-30" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-9" onclick="(()=>{console.log('text 9 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(205.455661 289.031269) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-32" />
|
||||
<use xlink:href="#DejaVuSans-Bold-31" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-10" onclick="(()=>{console.log('text 10 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(318.115269 306.990997) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-32" />
|
||||
<use xlink:href="#DejaVuSans-Bold-32" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-11" onclick="(()=>{console.log('text 11 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(459.755142 293.508014) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-32" />
|
||||
<use xlink:href="#DejaVuSans-Bold-33" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-12" onclick="(()=>{console.log('text 12 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(161.065175 271.9803) scale(0.12 -0.12)">
|
||||
<defs>
|
||||
<path id="DejaVuSans-Bold-38"
|
||||
d="M 2228 2088 Q 1891 2088 1709 1903 Q 1528 1719 1528 1375 Q 1528 1031 1709 848 Q 1891 666 2228 666 Q 2563 666 2741 848 Q 2919 1031 2919 1375 Q 2919 1722 2741 1905 Q 2563 2088 2228 2088 z M 1350 2484 Q 925 2613 709 2878 Q 494 3144 494 3541 Q 494 4131 934 4440 Q 1375 4750 2228 4750 Q 3075 4750 3515 4442 Q 3956 4134 3956 3541 Q 3956 3144 3739 2878 Q 3522 2613 3097 2484 Q 3572 2353 3814 2058 Q 4056 1763 4056 1313 Q 4056 619 3595 264 Q 3134 -91 2228 -91 Q 1319 -91 855 264 Q 391 619 391 1313 Q 391 1763 633 2058 Q 875 2353 1350 2484 z M 1631 3419 Q 1631 3141 1786 2991 Q 1941 2841 2228 2841 Q 2509 2841 2662 2991 Q 2816 3141 2816 3419 Q 2816 3697 2662 3845 Q 2509 3994 2228 3994 Q 1941 3994 1786 3844 Q 1631 3694 1631 3419 z "
|
||||
transform="scale(0.015625)" />
|
||||
</defs>
|
||||
<use xlink:href="#DejaVuSans-Bold-32" />
|
||||
<use xlink:href="#DejaVuSans-Bold-38" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-13" onclick="(()=>{console.log('text 13 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(244.173583 110.918523) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-33" />
|
||||
<use xlink:href="#DejaVuSans-Bold-31" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-14" onclick="(()=>{console.log('text 14 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(233.467625 161.664737) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-33" />
|
||||
<use xlink:href="#DejaVuSans-Bold-32" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-15" onclick="(()=>{console.log('text 15 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(270.491369 193.884188) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-33" />
|
||||
<use xlink:href="#DejaVuSans-Bold-33" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-16" onclick="(()=>{console.log('text 16 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(181.971765 226.625792) scale(0.12 -0.12)">
|
||||
<defs>
|
||||
<path id="DejaVuSans-Bold-34"
|
||||
d="M 2356 3675 L 1038 1722 L 2356 1722 L 2356 3675 z M 2156 4666 L 3494 4666 L 3494 1722 L 4159 1722 L 4159 850 L 3494 850 L 3494 0 L 2356 0 L 2356 850 L 288 850 L 288 1881 L 2156 4666 z "
|
||||
transform="scale(0.015625)" />
|
||||
</defs>
|
||||
<use xlink:href="#DejaVuSans-Bold-33" />
|
||||
<use xlink:href="#DejaVuSans-Bold-34" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-17" onclick="(()=>{console.log('text 17 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(225.063335 351.712921) scale(0.12 -0.12)">
|
||||
<defs>
|
||||
<path id="DejaVuSans-Bold-37"
|
||||
d="M 428 4666 L 3944 4666 L 3944 3988 L 2125 0 L 953 0 L 2675 3781 L 428 3781 L 428 4666 z "
|
||||
transform="scale(0.015625)" />
|
||||
</defs>
|
||||
<use xlink:href="#DejaVuSans-Bold-33" />
|
||||
<use xlink:href="#DejaVuSans-Bold-37" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-18" onclick="(()=>{console.log('text 18 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(113.946108 355.813803) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-34" />
|
||||
<use xlink:href="#DejaVuSans-Bold-31" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-19" onclick="(()=>{console.log('text 19 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(150.275227 403.77299) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-34" />
|
||||
<use xlink:href="#DejaVuSans-Bold-32" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-20" onclick="(()=>{console.log('text 20 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(206.056148 247.886269) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-34" />
|
||||
<use xlink:href="#DejaVuSans-Bold-34" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-21" onclick="(()=>{console.log('text 21 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(256.219988 226.341346) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-34" />
|
||||
<use xlink:href="#DejaVuSans-Bold-35" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-22" onclick="(()=>{console.log('text 22 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(212.447115 398.180721) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-34" />
|
||||
<use xlink:href="#DejaVuSans-Bold-36" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-23" onclick="(()=>{console.log('text 23 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(335.953598 169.601466) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-34" />
|
||||
<use xlink:href="#DejaVuSans-Bold-37" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-24" onclick="(()=>{console.log('text 24 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(232.971874 258.553808) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-34" />
|
||||
<use xlink:href="#DejaVuSans-Bold-38" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-25" onclick="(()=>{console.log('text 25 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(248.771502 299.468132) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-34" />
|
||||
<use xlink:href="#DejaVuSans-Bold-39" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-26" onclick="(()=>{console.log('text 26 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(199.213878 206.324585) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-35" />
|
||||
<use xlink:href="#DejaVuSans-Bold-30" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-27" onclick="(()=>{console.log('text 27 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(444.964679 332.520349) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-35" />
|
||||
<use xlink:href="#DejaVuSans-Bold-32" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-28" onclick="(()=>{console.log('text 28 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(341.774186 339.623355) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-35" />
|
||||
<use xlink:href="#DejaVuSans-Bold-34" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-29" onclick="(()=>{console.log('text 29 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(278.831389 312.87527) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-36" />
|
||||
<use xlink:href="#DejaVuSans-Bold-38" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-30" onclick="(()=>{console.log('text 30 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(279.080561 152.246589) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-37" />
|
||||
<use xlink:href="#DejaVuSans-Bold-30" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-31" onclick="(()=>{console.log('text 31 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(273.529238 281.158194) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-37" />
|
||||
<use xlink:href="#DejaVuSans-Bold-31" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-32" onclick="(()=>{console.log('text 32 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(292.28304 437.124218) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-37" />
|
||||
<use xlink:href="#DejaVuSans-Bold-33" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-33" onclick="(()=>{console.log('text 33 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(207.847093 320.425118) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-37" />
|
||||
<use xlink:href="#DejaVuSans-Bold-34" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-34" onclick="(()=>{console.log('text 34 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(411.155112 337.45314) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-37" />
|
||||
<use xlink:href="#DejaVuSans-Bold-35" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-35" onclick="(()=>{console.log('text 35 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(312.721831 137.338276) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-37" />
|
||||
<use xlink:href="#DejaVuSans-Bold-36" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-36" onclick="(()=>{console.log('text 36 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(358.165623 477.463977) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-37" />
|
||||
<use xlink:href="#DejaVuSans-Bold-37" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-37" onclick="(()=>{console.log('text 37 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(200.10369 364.776639) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-37" />
|
||||
<use xlink:href="#DejaVuSans-Bold-38" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-38" onclick="(()=>{console.log('text 38 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(228.300336 209.562933) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-37" />
|
||||
<use xlink:href="#DejaVuSans-Bold-39" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-39" onclick="(()=>{console.log('text 39 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(290.459616 239.607741) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-38" />
|
||||
<use xlink:href="#DejaVuSans-Bold-30" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-40" onclick="(()=>{console.log('text 40 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(173.595109 322.147003) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-38" />
|
||||
<use xlink:href="#DejaVuSans-Bold-31" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-41" onclick="(()=>{console.log('text 41 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(358.784874 437.766204) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-38" />
|
||||
<use xlink:href="#DejaVuSans-Bold-36" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-42" onclick="(()=>{console.log('text 42 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(413.927594 407.153606) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-38" />
|
||||
<use xlink:href="#DejaVuSans-Bold-37" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-43" onclick="(()=>{console.log('text 43 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(312.741682 407.26454) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-38" />
|
||||
<use xlink:href="#DejaVuSans-Bold-38" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-44" onclick="(()=>{console.log('text 44 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(154.095894 358.795699) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-38" />
|
||||
<use xlink:href="#DejaVuSans-Bold-39" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-45" onclick="(()=>{console.log('text 45 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(332.723876 275.599102) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-39" />
|
||||
<use xlink:href="#DejaVuSans-Bold-37" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-46" onclick="(()=>{console.log('text 46 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(380.950141 419.578314) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-39" />
|
||||
<use xlink:href="#DejaVuSans-Bold-38" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-47" onclick="(()=>{console.log('text 47 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(205.582536 438.239079) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-39" />
|
||||
<use xlink:href="#DejaVuSans-Bold-39" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-48" onclick="(()=>{console.log('text 48 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(423.537047 366.877303) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-31" />
|
||||
<use xlink:href="#DejaVuSans-Bold-30" x="69.580078" />
|
||||
<use xlink:href="#DejaVuSans-Bold-30" x="139.160156" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="pd42c8a995e">
|
||||
<rect x="85.985534" y="69.12" width="418.428931" height="443.52" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 54 KiB |
BIN
client/demo/dist/assets/buymeacoffee.png
vendored
Normal file
After Width: | Height: | Size: 12 KiB |
30
client/demo/dist/assets/gui_settings/GUI.json
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
{
|
||||
"type": "demo",
|
||||
"id": "RVC",
|
||||
"front": {
|
||||
"modelSlotControl": [
|
||||
{
|
||||
"name": "headerArea",
|
||||
"options": {
|
||||
"mainTitle": "Realtime Voice Changer Client",
|
||||
"subTitle": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "modelSlotArea",
|
||||
"options": {}
|
||||
},
|
||||
{
|
||||
"name": "characterArea",
|
||||
"options": {}
|
||||
},
|
||||
{
|
||||
"name": "configArea",
|
||||
"options": {
|
||||
"detectors": ["dio", "harvest", "crepe", "crepe_full", "crepe_tiny", "rmvpe", "rmvpe_onnx", "fcpe"],
|
||||
"inputChunkNums": [1, 2, 4, 6, 8, 16, 24, 32, 40, 48, 64, 80, 96, 112, 128, 192, 256, 320, 384, 448, 512, 576, 640, 704, 768, 832, 896, 960, 1024, 2048, 4096, 8192, 16384]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
30
client/demo/dist/assets/gui_settings/RVC.json
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
{
|
||||
"type": "demo",
|
||||
"id": "RVC",
|
||||
"front": {
|
||||
"modelSlotControl": [
|
||||
{
|
||||
"name": "headerArea",
|
||||
"options": {
|
||||
"mainTitle": "Realtime Voice Changer Client",
|
||||
"subTitle": "for RVC"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "modelSlotArea",
|
||||
"options": {}
|
||||
},
|
||||
{
|
||||
"name": "characterArea",
|
||||
"options": {}
|
||||
},
|
||||
{
|
||||
"name": "configArea",
|
||||
"options": {
|
||||
"detectors": ["dio", "harvest", "crepe"],
|
||||
"inputChunkNums": [8, 16, 24, 32, 40, 48, 64, 80, 96, 112, 128, 192, 256, 320, 384, 448, 512, 576, 640, 704, 768, 832, 896, 960, 1024, 2048]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
0
client/demo/dist/assets/gui_settings/edition.txt
vendored
Normal file
1
client/demo/dist/assets/gui_settings/edition_dml.txt
vendored
Normal file
@ -0,0 +1 @@
|
||||
onnxdirectML-cuda
|
1
client/demo/dist/assets/gui_settings/edition_web.txt
vendored
Normal file
@ -0,0 +1 @@
|
||||
web
|
1
client/demo/dist/assets/gui_settings/version.txt
vendored
Normal file
@ -0,0 +1 @@
|
||||
-.-.-.-
|
BIN
client/demo/dist/assets/icons/blank.png
vendored
Normal file
After Width: | Height: | Size: 1.4 KiB |
1
client/demo/dist/assets/icons/folder.svg
vendored
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-folder"><path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"></path></svg>
|
After Width: | Height: | Size: 311 B |
BIN
client/demo/dist/assets/icons/human.png
vendored
Normal file
After Width: | Height: | Size: 26 KiB |
BIN
client/demo/dist/assets/icons/noimage.png
vendored
Normal file
After Width: | Height: | Size: 2.1 KiB |
1
client/demo/dist/assets/icons/tool.svg
vendored
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-tool"><path d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z"></path></svg>
|
After Width: | Height: | Size: 386 B |
2
client/demo/dist/index.js
vendored
4
client/demo/dist/index.js.LICENSE.txt
vendored
@ -1,5 +1,9 @@
|
||||
/*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */
|
||||
|
||||
/*!**********************!*\
|
||||
!*** ./src/index.ts ***!
|
||||
\**********************/
|
||||
|
||||
/**
|
||||
* @license React
|
||||
* react-dom.production.min.js
|
||||
|
16825
client/demo/package-lock.json
generated
@ -4,13 +4,23 @@
|
||||
"description": "",
|
||||
"main": ".eslintrc.js",
|
||||
"scripts": {
|
||||
"clean": "rimraf dist/*",
|
||||
"clean": "rimraf dist/",
|
||||
"webpack:prod": "npx webpack --config webpack.prod.js",
|
||||
"webpack:dev": "npx webpack --config webpack.dev.js",
|
||||
"build:prod": "npm-run-all clean webpack:prod",
|
||||
"build:dev": "npm-run-all clean webpack:dev",
|
||||
"start": "webpack-dev-server --config webpack.dev.js",
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
"build:mod": "cd ../lib && npm run build:dev && cd - && cp -r ../lib/dist/* node_modules/@dannadori/voice-changer-client-js/dist/",
|
||||
"build:mod_dos": "cd ../lib && npm run build:dev && cd ../demo && npm-run-all build:mod_copy",
|
||||
"build:mod_copy": "XCOPY ..\\lib\\dist\\* .\\node_modules\\@dannadori\\voice-changer-client-js\\dist\\* /s /e /h /y",
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"____ comment ____": "ウェブバージョンのスクリプト",
|
||||
"clean:web": "rimraf dist_web/",
|
||||
"webpack:web:prod": "npx webpack --config webpack_web.prod.js && copy .\\public\\info_web .\\dist_web\\info && copy .\\public\\assets\\gui_settings\\edition_web.txt .\\dist_web\\assets\\gui_settings\\edition.txt",
|
||||
"webpack:web:dev": "npx webpack --config webpack_web.dev.js && copy .\\public\\info_web .\\dist_web\\info && copy .\\public\\assets\\gui_settings\\edition_web.txt .\\dist_web\\assets\\gui_settings\\edition.txt",
|
||||
"build:web:prod": "npm-run-all clean:web webpack:web:prod",
|
||||
"build:web:dev": "npm-run-all clean:web webpack:web:dev",
|
||||
"start:web": "webpack-dev-server --config webpack_web.dev.js"
|
||||
},
|
||||
"keywords": [
|
||||
"voice conversion"
|
||||
@ -18,39 +28,51 @@
|
||||
"author": "wataru.okada@flect.co.jp",
|
||||
"license": "ISC",
|
||||
"devDependencies": {
|
||||
"@babel/plugin-transform-runtime": "^7.19.6",
|
||||
"@babel/preset-env": "^7.20.2",
|
||||
"@babel/preset-react": "^7.18.6",
|
||||
"@babel/preset-typescript": "^7.18.6",
|
||||
"@types/node": "^18.11.18",
|
||||
"@types/react": "^18.0.27",
|
||||
"@types/react-dom": "^18.0.10",
|
||||
"autoprefixer": "^10.4.13",
|
||||
"babel-loader": "^9.1.2",
|
||||
"copy-webpack-plugin": "^11.0.0",
|
||||
"css-loader": "^6.7.3",
|
||||
"eslint": "^8.33.0",
|
||||
"eslint-config-prettier": "^8.6.0",
|
||||
"eslint-plugin-prettier": "^4.2.1",
|
||||
"eslint-plugin-react": "^7.32.1",
|
||||
"eslint-webpack-plugin": "^3.2.0",
|
||||
"html-loader": "^4.2.0",
|
||||
"html-webpack-plugin": "^5.5.0",
|
||||
"@babel/core": "^7.24.0",
|
||||
"@babel/plugin-transform-runtime": "^7.24.0",
|
||||
"@babel/preset-env": "^7.24.0",
|
||||
"@babel/preset-react": "^7.23.3",
|
||||
"@babel/preset-typescript": "^7.23.3",
|
||||
"@types/node": "^20.11.21",
|
||||
"@types/react": "^18.2.60",
|
||||
"@types/react-dom": "^18.2.19",
|
||||
"autoprefixer": "^10.4.17",
|
||||
"babel-loader": "^9.1.3",
|
||||
"copy-webpack-plugin": "^12.0.2",
|
||||
"css-loader": "^6.10.0",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"eslint-plugin-prettier": "^5.1.3",
|
||||
"eslint-plugin-react": "^7.33.2",
|
||||
"eslint-webpack-plugin": "^4.0.1",
|
||||
"html-loader": "^5.0.0",
|
||||
"html-webpack-plugin": "^5.6.0",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"postcss-loader": "^7.0.2",
|
||||
"postcss-nested": "^6.0.0",
|
||||
"prettier": "^2.8.3",
|
||||
"rimraf": "^4.1.2",
|
||||
"style-loader": "^3.3.1",
|
||||
"ts-loader": "^9.4.2",
|
||||
"tsconfig-paths": "^4.1.2",
|
||||
"typescript": "^4.9.4",
|
||||
"webpack": "^5.75.0",
|
||||
"webpack-cli": "^5.0.1",
|
||||
"webpack-dev-server": "^4.11.1"
|
||||
"postcss-loader": "^8.1.1",
|
||||
"postcss-nested": "^6.0.1",
|
||||
"prettier": "^3.2.5",
|
||||
"rimraf": "^5.0.5",
|
||||
"style-loader": "^3.3.4",
|
||||
"ts-loader": "^9.5.1",
|
||||
"tsconfig-paths": "^4.2.0",
|
||||
"typescript": "^5.3.3",
|
||||
"webpack": "^5.90.3",
|
||||
"webpack-cli": "^5.1.4",
|
||||
"webpack-dev-server": "^5.0.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@dannadori/voice-changer-client-js": "^1.0.66",
|
||||
"@alexanderolsen/libsamplerate-js": "^2.1.1",
|
||||
"@dannadori/voice-changer-client-js": "^1.0.182",
|
||||
"@dannadori/voice-changer-js": "^1.0.2",
|
||||
"@dannadori/worker-manager": "^1.0.20",
|
||||
"@fortawesome/fontawesome-svg-core": "^6.5.1",
|
||||
"@fortawesome/free-brands-svg-icons": "^6.5.1",
|
||||
"@fortawesome/free-regular-svg-icons": "^6.5.1",
|
||||
"@fortawesome/free-solid-svg-icons": "^6.5.1",
|
||||
"@fortawesome/react-fontawesome": "^0.2.0",
|
||||
"@tensorflow/tfjs": "^4.17.0",
|
||||
"onnxruntime-web": "^1.17.1",
|
||||
"protobufjs": "^7.2.6",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0"
|
||||
}
|
||||
|
928
client/demo/public/assets/beatrice/female-clickable.svg
Normal file
@ -0,0 +1,928 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:ns2="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink" width="100%" height="100%" viewBox="100 60 420 450" version="1.1">
|
||||
<metadata>
|
||||
<rdf:RDF>
|
||||
<ns2:Work>
|
||||
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:date>2023-11-19T11:21:56.358384</dc:date>
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:creator>
|
||||
<ns2:Agent>
|
||||
<dc:title>Matplotlib v3.7.1, https://matplotlib.org/</dc:title>
|
||||
</ns2:Agent>
|
||||
</dc:creator>
|
||||
</ns2:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs>
|
||||
<style type="text/css">
|
||||
* {
|
||||
stroke-linejoin: round;
|
||||
stroke-linecap: butt
|
||||
}
|
||||
</style>
|
||||
<style type="text/css">
|
||||
.beatrice-node-pointer {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.beatrice-node-pointer:hover {
|
||||
stroke: gray;
|
||||
}
|
||||
|
||||
.beatrice-node-pointer-selected {
|
||||
stroke: #ef6767c2;
|
||||
stroke-width: 3
|
||||
}
|
||||
|
||||
.beatrice-text-pointer {
|
||||
cursor: pointer;
|
||||
pointer-events: none
|
||||
}
|
||||
|
||||
.beatrice-text-pointer:hover {
|
||||
/* ホバー時のスタイルは既に設定されたスタイルと異なる特定の属性を変更することができます。 */
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<g id="figure_1">
|
||||
<g id="patch_1">
|
||||
<path d="M 0 576 L 576 576 L 576 0 L 0 0 z " style="fill: #ffffff" />
|
||||
</g>
|
||||
<g id="axes_1">
|
||||
<g id="LineCollection_1">
|
||||
<path d="M 403.96157 149.258085 L 366.630583 148.159991 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 396.547407 371.476481 L 372.120414 365.421971 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 396.547407 371.476481 L 416.760989 346.999139 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 396.547407 371.476481 L 404.238335 402.754731 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 258.035169 326.134244 L 298.859694 332.465911 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 167.453327 366.897955 L 203.987537 347.931194 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 436.352807 416.173738 L 404.238335 402.754731 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 391.514336 242.048236 L 417.560846 259.464346 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 391.514336 242.048236 L 355.734145 235.68791 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 391.514336 242.048236 L 424.070309 219.021704 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 205.541044 459.711101 L 230.303076 436.148139 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 160.44225 292.540336 L 167.396334 325.961848 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 345.679012 107.607273 L 366.630583 148.159991 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 325.345004 219.195921 L 355.734145 235.68791 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 325.345004 219.195921 L 297.530501 194.55124 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 363.075301 201.701937 L 355.734145 235.68791 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 363.075301 201.701937 L 341.462109 170.414842 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 366.630583 148.159991 L 341.462109 170.414842 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 167.396334 325.961848 L 203.987537 347.931194 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 262.111309 181.887977 L 297.530501 194.55124 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 189.293496 262.735141 L 222.122563 261.416721 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 277.95603 462.622539 L 293.230217 421.393405 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 333.932593 269.342364 L 301.9174 258.124913 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 333.932593 269.342364 L 355.734145 235.68791 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 334.666605 338.097578 L 320.07566 368.578481 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 203.987537 347.931194 L 242.811958 354.082183 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 288.059985 363.924972 L 320.07566 368.578481 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 288.059985 363.924972 L 276.198518 388.99868 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 288.059985 363.924972 L 298.859694 332.465911 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 288.059985 363.924972 L 242.811958 354.082183 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 276.198518 388.99868 L 293.230217 421.393405 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 293.230217 421.393405 L 309.530924 454.827332 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 293.230217 421.393405 L 260.004712 426.426278 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 423.853712 378.321354 L 404.238335 402.754731 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 205.214352 217.066163 L 222.122563 261.416721 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 154.047193 423.153273 L 193.933786 408.004355 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 298.859694 332.465911 L 277.79477 306.980241 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 277.79477 306.980241 L 282.261978 282.779534 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 260.004712 426.426278 L 230.303076 436.148139 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 260.004712 426.426278 L 228.689744 409.959215 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 260.004712 426.426278 L 261.506403 474.152727 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 301.9174 258.124913 L 282.261978 282.779534 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 254.897329 263.033159 L 282.261978 282.779534 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 254.897329 263.033159 L 222.122563 261.416721 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 321.267463 403.021207 L 320.07566 368.578481 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 345.750267 380.131711 L 320.07566 368.578481 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 345.750267 380.131711 L 372.120414 365.421971 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 345.750267 380.131711 L 351.226176 419.342667 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 404.238335 402.754731 L 400.607869 434.730447 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 193.933786 408.004355 L 230.303076 436.148139 " clip-path="url(#pe3de578e26)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
</g>
|
||||
<g id="PathCollection_1">
|
||||
<defs>
|
||||
<path id="C0_0_b0ffb3bf4a"
|
||||
d="M 0 11.18034 C 2.965061 11.18034 5.80908 10.002309 7.905694 7.905694 C 10.002309 5.80908 11.18034 2.965061 11.18034 -0 C 11.18034 -2.965061 10.002309 -5.80908 7.905694 -7.905694 C 5.80908 -10.002309 2.965061 -11.18034 0 -11.18034 C -2.965061 -11.18034 -5.80908 -10.002309 -7.905694 -7.905694 C -10.002309 -5.80908 -11.18034 -2.965061 -11.18034 0 C -11.18034 2.965061 -10.002309 5.80908 -7.905694 7.905694 C -5.80908 10.002309 -2.965061 11.18034 0 11.18034 z " />
|
||||
</defs>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-0"
|
||||
onclick="(()=>{console.log('node 0')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="403.96157" y="149.258085" style="fill: #e7f5d2" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-1"
|
||||
onclick="(()=>{console.log('node 1')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="396.547407" y="371.476481" style="fill: #fbe8f2" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-2"
|
||||
onclick="(()=>{console.log('node 2')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="258.035169" y="326.134244" style="fill: #cfebaa" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-3"
|
||||
onclick="(()=>{console.log('node 3')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="167.453327" y="366.897955" style="fill: #f1f6e8" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-4"
|
||||
onclick="(()=>{console.log('node 4')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="436.352807" y="416.173738" style="fill: #e89ac6" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-5"
|
||||
onclick="(()=>{console.log('node 5')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="391.514336" y="242.048236" style="fill: #f3bcdd" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-6"
|
||||
onclick="(()=>{console.log('node 6')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="205.541044" y="459.711101" style="fill: #fbd9ec" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-7"
|
||||
onclick="(()=>{console.log('node 7')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="160.44225" y="292.540336" style="fill: #9ed067" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-8"
|
||||
onclick="(()=>{console.log('node 8')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="424.070309" y="219.021704" style="fill: #e1f3c7" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-9"
|
||||
onclick="(()=>{console.log('node 9')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="345.679012" y="107.607273" style="fill: #d0ecad" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-10"
|
||||
onclick="(()=>{console.log('node 10')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="325.345004" y="219.195921" style="fill: #eff6e4" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-11"
|
||||
onclick="(()=>{console.log('node 11')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="363.075301" y="201.701937" style="fill: #f9f0f5" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-12"
|
||||
onclick="(()=>{console.log('node 12')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="366.630583" y="148.159991" style="fill: #ebf6dc" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-13"
|
||||
onclick="(()=>{console.log('node 13')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="341.462109" y="170.414842" style="fill: #fad6ea" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-14"
|
||||
onclick="(()=>{console.log('node 14')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="167.396334" y="325.961848" style="fill: #f5f7f3" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-15"
|
||||
onclick="(()=>{console.log('node 15')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="262.111309" y="181.887977" style="fill: #e9f5d6" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-16"
|
||||
onclick="(()=>{console.log('node 16')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="189.293496" y="262.735141" style="fill: #fce5f1" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-17"
|
||||
onclick="(()=>{console.log('node 17')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="277.95603" y="462.622539" style="fill: #c4e699" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-18"
|
||||
onclick="(()=>{console.log('node 18')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="333.932593" y="269.342364" style="fill: #f8f4f6" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-19"
|
||||
onclick="(()=>{console.log('node 19')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="416.760989" y="346.999139" style="fill: #eef6e2" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-20"
|
||||
onclick="(()=>{console.log('node 20')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="334.666605" y="338.097578" style="fill: #f5f7f3" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-21"
|
||||
onclick="(()=>{console.log('node 21')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="203.987537" y="347.931194" style="fill: #edf6df" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-22"
|
||||
onclick="(()=>{console.log('node 22')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="288.059985" y="363.924972" style="fill: #ddf1c1" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-23"
|
||||
onclick="(()=>{console.log('node 23')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="276.198518" y="388.99868" style="fill: #f5f7f3" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-24"
|
||||
onclick="(()=>{console.log('node 24')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="293.230217" y="421.393405" style="fill: #f3f7ef" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-25"
|
||||
onclick="(()=>{console.log('node 25')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="423.853712" y="378.321354" style="fill: #edf6df" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-26"
|
||||
onclick="(()=>{console.log('node 26')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="205.214352" y="217.066163" style="fill: #e7f5d2" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-27"
|
||||
onclick="(()=>{console.log('node 27')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="242.811958" y="354.082183" style="fill: #d2ecb0" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-28"
|
||||
onclick="(()=>{console.log('node 28')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="154.047193" y="423.153273" style="fill: #e6f5d0" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-29"
|
||||
onclick="(()=>{console.log('node 29')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="298.859694" y="332.465911" style="fill: #ecf6de" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-30"
|
||||
onclick="(()=>{console.log('node 30')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="277.79477" y="306.980241" style="fill: #eaf5d9" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-31"
|
||||
onclick="(()=>{console.log('node 31')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="260.004712" y="426.426278" style="fill: #f9f1f5" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-32"
|
||||
onclick="(()=>{console.log('node 32')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="301.9174" y="258.124913" style="fill: #dbf0bf" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-33"
|
||||
onclick="(()=>{console.log('node 33')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="254.897329" y="263.033159" style="fill: #eff6e4" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-34"
|
||||
onclick="(()=>{console.log('node 34')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="321.267463" y="403.021207" style="fill: #d0ecad" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-35"
|
||||
onclick="(()=>{console.log('node 35')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="345.750267" y="380.131711" style="fill: #f9eef4" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-36"
|
||||
onclick="(()=>{console.log('node 36')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="404.238335" y="402.754731" style="fill: #f9eef4" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-37"
|
||||
onclick="(()=>{console.log('node 37')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="355.734145" y="235.68791" style="fill: #f9eef4" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-38"
|
||||
onclick="(()=>{console.log('node 38')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="193.933786" y="408.004355" style="fill: #f0f6e7" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-39"
|
||||
onclick="(()=>{console.log('node 39')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="297.530501" y="194.55124" style="fill: #f3f6ed" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-40"
|
||||
onclick="(()=>{console.log('node 40')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="320.07566" y="368.578481" style="fill: #dbf0bf" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-41"
|
||||
onclick="(()=>{console.log('node 41')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="228.689744" y="409.959215" style="fill: #f9eff4" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-42"
|
||||
onclick="(()=>{console.log('node 42')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="351.226176" y="419.342667" style="fill: #cfebaa" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-43"
|
||||
onclick="(()=>{console.log('node 43')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="372.120414" y="365.421971" style="fill: #f7f6f7" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-44"
|
||||
onclick="(()=>{console.log('node 44')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="230.303076" y="436.148139" style="fill: #f8cee6" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-45"
|
||||
onclick="(()=>{console.log('node 45')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="261.506403" y="474.152727" style="fill: #e6f5d0" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-46"
|
||||
onclick="(()=>{console.log('node 46')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="417.560846" y="259.464346" style="fill: #b7e085" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-47"
|
||||
onclick="(()=>{console.log('node 47')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="400.607869" y="434.730447" style="fill: #f8cee6" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-48"
|
||||
onclick="(()=>{console.log('node 48')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="282.261978" y="282.779534" style="fill: #d6eeb6" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-49"
|
||||
onclick="(()=>{console.log('node 49')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="222.122563" y="261.416721" style="fill: #edf6df" />
|
||||
</g>
|
||||
<g clip-path="url(#pe3de578e26)" id="beatrice-node-female-50"
|
||||
onclick="(()=>{console.log('node 50')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_b0ffb3bf4a" x="309.530924" y="454.827332" style="fill: #f9eef4" />
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-0" onclick="(()=>{console.log('text 0 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(399.786883 152.569335) scale(0.12 -0.12)">
|
||||
<defs>
|
||||
<path id="DejaVuSans-Bold-32"
|
||||
d="M 1844 884 L 3897 884 L 3897 0 L 506 0 L 506 884 L 2209 2388 Q 2438 2594 2547 2791 Q 2656 2988 2656 3200 Q 2656 3528 2436 3728 Q 2216 3928 1850 3928 Q 1569 3928 1234 3808 Q 900 3688 519 3450 L 519 4475 Q 925 4609 1322 4679 Q 1719 4750 2100 4750 Q 2938 4750 3402 4381 Q 3866 4013 3866 3353 Q 3866 2972 3669 2642 Q 3472 2313 2841 1759 L 1844 884 z "
|
||||
transform="scale(0.015625)" />
|
||||
</defs>
|
||||
<use xlink:href="#DejaVuSans-Bold-32" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-1" onclick="(()=>{console.log('text 1 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(392.37272 374.787731) scale(0.12 -0.12)">
|
||||
<defs>
|
||||
<path id="DejaVuSans-Bold-34"
|
||||
d="M 2356 3675 L 1038 1722 L 2356 1722 L 2356 3675 z M 2156 4666 L 3494 4666 L 3494 1722 L 4159 1722 L 4159 850 L 3494 850 L 3494 0 L 2356 0 L 2356 850 L 288 850 L 288 1881 L 2156 4666 z "
|
||||
transform="scale(0.015625)" />
|
||||
</defs>
|
||||
<use xlink:href="#DejaVuSans-Bold-34" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-2" onclick="(()=>{console.log('text 2 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(253.860482 329.445494) scale(0.12 -0.12)">
|
||||
<defs>
|
||||
<path id="DejaVuSans-Bold-37"
|
||||
d="M 428 4666 L 3944 4666 L 3944 3988 L 2125 0 L 953 0 L 2675 3781 L 428 3781 L 428 4666 z "
|
||||
transform="scale(0.015625)" />
|
||||
</defs>
|
||||
<use xlink:href="#DejaVuSans-Bold-37" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-3" onclick="(()=>{console.log('text 3 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(163.27864 370.209205) scale(0.12 -0.12)">
|
||||
<defs>
|
||||
<path id="DejaVuSans-Bold-38"
|
||||
d="M 2228 2088 Q 1891 2088 1709 1903 Q 1528 1719 1528 1375 Q 1528 1031 1709 848 Q 1891 666 2228 666 Q 2563 666 2741 848 Q 2919 1031 2919 1375 Q 2919 1722 2741 1905 Q 2563 2088 2228 2088 z M 1350 2484 Q 925 2613 709 2878 Q 494 3144 494 3541 Q 494 4131 934 4440 Q 1375 4750 2228 4750 Q 3075 4750 3515 4442 Q 3956 4134 3956 3541 Q 3956 3144 3739 2878 Q 3522 2613 3097 2484 Q 3572 2353 3814 2058 Q 4056 1763 4056 1313 Q 4056 619 3595 264 Q 3134 -91 2228 -91 Q 1319 -91 855 264 Q 391 619 391 1313 Q 391 1763 633 2058 Q 875 2353 1350 2484 z M 1631 3419 Q 1631 3141 1786 2991 Q 1941 2841 2228 2841 Q 2509 2841 2662 2991 Q 2816 3141 2816 3419 Q 2816 3697 2662 3845 Q 2509 3994 2228 3994 Q 1941 3994 1786 3844 Q 1631 3694 1631 3419 z "
|
||||
transform="scale(0.015625)" />
|
||||
</defs>
|
||||
<use xlink:href="#DejaVuSans-Bold-38" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-4" onclick="(()=>{console.log('text 4 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(428.003432 419.484988) scale(0.12 -0.12)">
|
||||
<defs>
|
||||
<path id="DejaVuSans-Bold-31"
|
||||
d="M 750 831 L 1813 831 L 1813 3847 L 722 3622 L 722 4441 L 1806 4666 L 2950 4666 L 2950 831 L 4013 831 L 4013 0 L 750 0 L 750 831 z "
|
||||
transform="scale(0.015625)" />
|
||||
<path id="DejaVuSans-Bold-30"
|
||||
d="M 2944 2338 Q 2944 3213 2780 3570 Q 2616 3928 2228 3928 Q 1841 3928 1675 3570 Q 1509 3213 1509 2338 Q 1509 1453 1675 1090 Q 1841 728 2228 728 Q 2613 728 2778 1090 Q 2944 1453 2944 2338 z M 4147 2328 Q 4147 1169 3647 539 Q 3147 -91 2228 -91 Q 1306 -91 806 539 Q 306 1169 306 2328 Q 306 3491 806 4120 Q 1306 4750 2228 4750 Q 3147 4750 3647 4120 Q 4147 3491 4147 2328 z "
|
||||
transform="scale(0.015625)" />
|
||||
</defs>
|
||||
<use xlink:href="#DejaVuSans-Bold-31" />
|
||||
<use xlink:href="#DejaVuSans-Bold-30" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-5" onclick="(()=>{console.log('text 5 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(383.164961 245.359486) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-31" />
|
||||
<use xlink:href="#DejaVuSans-Bold-34" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-6" onclick="(()=>{console.log('text 6 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(197.191669 463.022351) scale(0.12 -0.12)">
|
||||
<defs>
|
||||
<path id="DejaVuSans-Bold-35"
|
||||
d="M 678 4666 L 3669 4666 L 3669 3781 L 1638 3781 L 1638 3059 Q 1775 3097 1914 3117 Q 2053 3138 2203 3138 Q 3056 3138 3531 2711 Q 4006 2284 4006 1522 Q 4006 766 3489 337 Q 2972 -91 2053 -91 Q 1656 -91 1267 -14 Q 878 63 494 219 L 494 1166 Q 875 947 1217 837 Q 1559 728 1863 728 Q 2300 728 2551 942 Q 2803 1156 2803 1522 Q 2803 1891 2551 2103 Q 2300 2316 1863 2316 Q 1603 2316 1309 2248 Q 1016 2181 678 2041 L 678 4666 z "
|
||||
transform="scale(0.015625)" />
|
||||
</defs>
|
||||
<use xlink:href="#DejaVuSans-Bold-31" />
|
||||
<use xlink:href="#DejaVuSans-Bold-35" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-7" onclick="(()=>{console.log('text 7 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(152.092875 295.851586) scale(0.12 -0.12)">
|
||||
<defs>
|
||||
<path id="DejaVuSans-Bold-36"
|
||||
d="M 2316 2303 Q 2000 2303 1842 2098 Q 1684 1894 1684 1484 Q 1684 1075 1842 870 Q 2000 666 2316 666 Q 2634 666 2792 870 Q 2950 1075 2950 1484 Q 2950 1894 2792 2098 Q 2634 2303 2316 2303 z M 3803 4544 L 3803 3681 Q 3506 3822 3243 3889 Q 2981 3956 2731 3956 Q 2194 3956 1894 3657 Q 1594 3359 1544 2772 Q 1750 2925 1990 3001 Q 2231 3078 2516 3078 Q 3231 3078 3670 2659 Q 4109 2241 4109 1563 Q 4109 813 3618 361 Q 3128 -91 2303 -91 Q 1394 -91 895 523 Q 397 1138 397 2266 Q 397 3422 980 4083 Q 1563 4744 2578 4744 Q 2900 4744 3203 4694 Q 3506 4644 3803 4544 z "
|
||||
transform="scale(0.015625)" />
|
||||
</defs>
|
||||
<use xlink:href="#DejaVuSans-Bold-31" />
|
||||
<use xlink:href="#DejaVuSans-Bold-36" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-8" onclick="(()=>{console.log('text 8 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(415.720934 222.332954) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-31" />
|
||||
<use xlink:href="#DejaVuSans-Bold-37" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-9" onclick="(()=>{console.log('text 9 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(337.329637 110.918523) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-31" />
|
||||
<use xlink:href="#DejaVuSans-Bold-38" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-10" onclick="(()=>{console.log('text 10 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(316.995629 222.507171) scale(0.12 -0.12)">
|
||||
<defs>
|
||||
<path id="DejaVuSans-Bold-39"
|
||||
d="M 641 103 L 641 966 Q 928 831 1190 764 Q 1453 697 1709 697 Q 2247 697 2547 995 Q 2847 1294 2900 1881 Q 2688 1725 2447 1647 Q 2206 1569 1925 1569 Q 1209 1569 770 1986 Q 331 2403 331 3084 Q 331 3838 820 4291 Q 1309 4744 2131 4744 Q 3044 4744 3544 4128 Q 4044 3513 4044 2388 Q 4044 1231 3459 570 Q 2875 -91 1856 -91 Q 1528 -91 1228 -42 Q 928 6 641 103 z M 2125 2350 Q 2441 2350 2600 2554 Q 2759 2759 2759 3169 Q 2759 3575 2600 3781 Q 2441 3988 2125 3988 Q 1809 3988 1650 3781 Q 1491 3575 1491 3169 Q 1491 2759 1650 2554 Q 1809 2350 2125 2350 z "
|
||||
transform="scale(0.015625)" />
|
||||
</defs>
|
||||
<use xlink:href="#DejaVuSans-Bold-31" />
|
||||
<use xlink:href="#DejaVuSans-Bold-39" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-11" onclick="(()=>{console.log('text 11 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(354.725926 205.013187) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-32" />
|
||||
<use xlink:href="#DejaVuSans-Bold-34" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-12" onclick="(()=>{console.log('text 12 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(358.281208 151.471241) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-32" />
|
||||
<use xlink:href="#DejaVuSans-Bold-35" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-13" onclick="(()=>{console.log('text 13 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(333.112734 173.726092) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-32" />
|
||||
<use xlink:href="#DejaVuSans-Bold-36" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-14" onclick="(()=>{console.log('text 14 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(159.046959 329.273098) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-32" />
|
||||
<use xlink:href="#DejaVuSans-Bold-37" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-15" onclick="(()=>{console.log('text 15 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(253.761934 185.199227) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-32" />
|
||||
<use xlink:href="#DejaVuSans-Bold-39" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-16" onclick="(()=>{console.log('text 16 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(180.944121 266.046391) scale(0.12 -0.12)">
|
||||
<defs>
|
||||
<path id="DejaVuSans-Bold-33"
|
||||
d="M 2981 2516 Q 3453 2394 3698 2092 Q 3944 1791 3944 1325 Q 3944 631 3412 270 Q 2881 -91 1863 -91 Q 1503 -91 1142 -33 Q 781 25 428 141 L 428 1069 Q 766 900 1098 814 Q 1431 728 1753 728 Q 2231 728 2486 893 Q 2741 1059 2741 1369 Q 2741 1688 2480 1852 Q 2219 2016 1709 2016 L 1228 2016 L 1228 2791 L 1734 2791 Q 2188 2791 2409 2933 Q 2631 3075 2631 3366 Q 2631 3634 2415 3781 Q 2200 3928 1806 3928 Q 1516 3928 1219 3862 Q 922 3797 628 3669 L 628 4550 Q 984 4650 1334 4700 Q 1684 4750 2022 4750 Q 2931 4750 3382 4451 Q 3834 4153 3834 3553 Q 3834 3144 3618 2883 Q 3403 2622 2981 2516 z "
|
||||
transform="scale(0.015625)" />
|
||||
</defs>
|
||||
<use xlink:href="#DejaVuSans-Bold-33" />
|
||||
<use xlink:href="#DejaVuSans-Bold-30" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-17" onclick="(()=>{console.log('text 17 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(269.606655 465.933789) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-33" />
|
||||
<use xlink:href="#DejaVuSans-Bold-35" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-18" onclick="(()=>{console.log('text 18 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(325.583218 272.653614) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-33" />
|
||||
<use xlink:href="#DejaVuSans-Bold-36" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-19" onclick="(()=>{console.log('text 19 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(408.411614 350.310389) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-33" />
|
||||
<use xlink:href="#DejaVuSans-Bold-38" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-20" onclick="(()=>{console.log('text 20 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(326.31723 341.408828) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-33" />
|
||||
<use xlink:href="#DejaVuSans-Bold-39" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-21" onclick="(()=>{console.log('text 21 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(195.638162 351.242444) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-34" />
|
||||
<use xlink:href="#DejaVuSans-Bold-30" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-22" onclick="(()=>{console.log('text 22 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(279.71061 367.236222) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-34" />
|
||||
<use xlink:href="#DejaVuSans-Bold-33" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-23" onclick="(()=>{console.log('text 23 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(267.849143 392.30993) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-35" />
|
||||
<use xlink:href="#DejaVuSans-Bold-31" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-24" onclick="(()=>{console.log('text 24 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(284.880842 424.704655) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-35" />
|
||||
<use xlink:href="#DejaVuSans-Bold-33" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-25" onclick="(()=>{console.log('text 25 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(415.504337 381.632604) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-35" />
|
||||
<use xlink:href="#DejaVuSans-Bold-35" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-26" onclick="(()=>{console.log('text 26 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(196.864977 220.377413) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-35" />
|
||||
<use xlink:href="#DejaVuSans-Bold-36" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-27" onclick="(()=>{console.log('text 27 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(234.462583 357.393433) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-35" />
|
||||
<use xlink:href="#DejaVuSans-Bold-37" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-28" onclick="(()=>{console.log('text 28 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(145.697818 426.464523) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-35" />
|
||||
<use xlink:href="#DejaVuSans-Bold-38" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-29" onclick="(()=>{console.log('text 29 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(290.510319 335.777161) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-35" />
|
||||
<use xlink:href="#DejaVuSans-Bold-39" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-30" onclick="(()=>{console.log('text 30 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(269.445395 310.291491) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-36" />
|
||||
<use xlink:href="#DejaVuSans-Bold-30" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-31" onclick="(()=>{console.log('text 31 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(251.655337 429.737528) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-36" />
|
||||
<use xlink:href="#DejaVuSans-Bold-31" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-32" onclick="(()=>{console.log('text 32 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(293.568025 261.436163) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-36" />
|
||||
<use xlink:href="#DejaVuSans-Bold-32" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-33" onclick="(()=>{console.log('text 33 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(246.547954 266.344409) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-36" />
|
||||
<use xlink:href="#DejaVuSans-Bold-33" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-34" onclick="(()=>{console.log('text 34 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(312.918088 406.332457) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-36" />
|
||||
<use xlink:href="#DejaVuSans-Bold-34" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-35" onclick="(()=>{console.log('text 35 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(337.400892 383.442961) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-36" />
|
||||
<use xlink:href="#DejaVuSans-Bold-35" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-36" onclick="(()=>{console.log('text 36 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(395.88896 406.065981) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-36" />
|
||||
<use xlink:href="#DejaVuSans-Bold-36" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-37" onclick="(()=>{console.log('text 37 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(347.38477 238.99916) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-36" />
|
||||
<use xlink:href="#DejaVuSans-Bold-37" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-38" onclick="(()=>{console.log('text 38 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(185.584411 411.315605) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-36" />
|
||||
<use xlink:href="#DejaVuSans-Bold-39" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-39" onclick="(()=>{console.log('text 39 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(289.181126 197.86249) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-37" />
|
||||
<use xlink:href="#DejaVuSans-Bold-32" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-40" onclick="(()=>{console.log('text 40 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(311.726285 371.889731) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-38" />
|
||||
<use xlink:href="#DejaVuSans-Bold-32" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-41" onclick="(()=>{console.log('text 41 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(220.340369 413.270465) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-38" />
|
||||
<use xlink:href="#DejaVuSans-Bold-33" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-42" onclick="(()=>{console.log('text 42 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(342.876801 422.653917) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-38" />
|
||||
<use xlink:href="#DejaVuSans-Bold-34" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-43" onclick="(()=>{console.log('text 43 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(363.771039 368.733221) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-38" />
|
||||
<use xlink:href="#DejaVuSans-Bold-35" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-44" onclick="(()=>{console.log('text 44 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(221.953701 439.459389) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-39" />
|
||||
<use xlink:href="#DejaVuSans-Bold-30" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-45" onclick="(()=>{console.log('text 45 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(253.157028 477.463977) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-39" />
|
||||
<use xlink:href="#DejaVuSans-Bold-31" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-46" onclick="(()=>{console.log('text 46 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(409.211471 262.775596) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-39" />
|
||||
<use xlink:href="#DejaVuSans-Bold-32" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-47" onclick="(()=>{console.log('text 47 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(392.258494 438.041697) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-39" />
|
||||
<use xlink:href="#DejaVuSans-Bold-33" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-48" onclick="(()=>{console.log('text 48 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(273.912603 286.090784) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-39" />
|
||||
<use xlink:href="#DejaVuSans-Bold-34" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-49" onclick="(()=>{console.log('text 49 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(213.773188 264.727971) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-39" />
|
||||
<use xlink:href="#DejaVuSans-Bold-35" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-female-50" onclick="(()=>{console.log('text 50 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pe3de578e26)">
|
||||
|
||||
<g transform="translate(301.181549 458.138582) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-39" />
|
||||
<use xlink:href="#DejaVuSans-Bold-36" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="pe3de578e26">
|
||||
<rect x="124.405104" y="69.12" width="341.589792" height="443.52" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 56 KiB |
898
client/demo/public/assets/beatrice/male-clickable.svg
Normal file
@ -0,0 +1,898 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:ns2="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink" width="100%" height="100%" viewBox="100 60 420 450" version="1.1">
|
||||
<metadata>
|
||||
<rdf:RDF>
|
||||
<ns2:Work>
|
||||
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:date>2023-11-19T11:21:55.705408</dc:date>
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:creator>
|
||||
<ns2:Agent>
|
||||
<dc:title>Matplotlib v3.7.1, https://matplotlib.org/</dc:title>
|
||||
</ns2:Agent>
|
||||
</dc:creator>
|
||||
</ns2:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs>
|
||||
<style type="text/css">
|
||||
* {
|
||||
stroke-linejoin: round;
|
||||
stroke-linecap: butt
|
||||
}
|
||||
</style>
|
||||
<style type="text/css">
|
||||
.beatrice-node-pointer {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.beatrice-node-pointer:hover {
|
||||
stroke: gray;
|
||||
}
|
||||
|
||||
.beatrice-node-pointer-selected {
|
||||
stroke: #ef6767c2;
|
||||
stroke-width: 3
|
||||
}
|
||||
|
||||
.beatrice-text-pointer {
|
||||
cursor: pointer;
|
||||
pointer-events: none
|
||||
}
|
||||
|
||||
.beatrice-text-pointer:hover {
|
||||
/* ホバー時のスタイルは既に設定されたスタイルと異なる特定の属性を変更することができます。 */
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<g id="figure_1">
|
||||
<g id="patch_1">
|
||||
<path d="M 0 576 L 576 576 L 576 0 L 0 0 z " style="fill: #ffffff" />
|
||||
</g>
|
||||
<g id="axes_1">
|
||||
<g id="LineCollection_1">
|
||||
<path d="M 383.475478 335.382791 L 350.123561 336.312105 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 383.475478 335.382791 L 393.562573 295.917472 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 383.475478 335.382791 L 396.396073 371.656412 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 395.592267 184.349842 L 344.302973 166.290216 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 166.614267 246.553188 L 214.405523 244.575019 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 362.886037 395.352171 L 389.299516 416.267064 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 362.886037 395.352171 L 367.134249 434.454954 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 362.886037 395.352171 L 396.396073 371.656412 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 362.886037 395.352171 L 321.091057 403.95329 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 291.699254 114.456198 L 287.429936 148.935339 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 309.72476 346.813492 L 326.464644 303.679747 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 396.396073 371.656412 L 422.276969 403.842356 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 396.396073 371.656412 L 419.504487 334.14189 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 311.713 188.802087 L 278.840744 190.572938 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 311.713 188.802087 L 287.429936 148.935339 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 311.713 188.802087 L 344.302973 166.290216 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 213.805036 285.720019 L 216.196468 317.113868 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 213.805036 285.720019 L 241.321249 255.242558 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 213.805036 285.720019 L 169.41455 268.66905 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 326.464644 303.679747 L 341.073251 272.287852 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 326.464644 303.679747 L 281.878613 277.846944 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 326.464644 303.679747 L 350.123561 336.312105 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 468.104517 290.196764 L 453.314054 329.209099 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 252.522958 107.607273 L 287.429936 148.935339 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 241.817 158.353487 L 278.840744 190.572938 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 278.840744 190.572938 L 264.569363 223.030096 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 190.32114 223.314542 L 214.405523 244.575019 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 233.41271 348.401671 L 216.196468 317.113868 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 122.295483 352.502553 L 162.445269 355.484449 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 158.624602 400.46174 L 162.445269 355.484449 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 214.405523 244.575019 L 241.321249 255.242558 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 214.405523 244.575019 L 207.563253 203.013335 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 264.569363 223.030096 L 298.808991 236.296491 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 264.569363 223.030096 L 241.321249 255.242558 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 264.569363 223.030096 L 236.649711 206.251683 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 220.79649 394.869471 L 213.931911 434.927829 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 220.79649 394.869471 L 208.453065 361.465389 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 241.321249 255.242558 L 281.878613 277.846944 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 257.120877 296.156882 L 281.878613 277.846944 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 453.314054 329.209099 L 419.504487 334.14189 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 287.180764 309.56402 L 281.878613 277.846944 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 287.429936 148.935339 L 321.071206 134.027026 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 300.632415 433.812968 L 321.091057 403.95329 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 216.196468 317.113868 L 181.944484 318.835753 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 216.196468 317.113868 L 208.453065 361.465389 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 419.504487 334.14189 L 436.061109 363.566053 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 366.514998 474.152727 L 367.134249 434.454954 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
<path d="M 208.453065 361.465389 L 162.445269 355.484449 " clip-path="url(#pd42c8a995e)"
|
||||
style="fill: none; stroke: #808080" />
|
||||
</g>
|
||||
<g id="PathCollection_1">
|
||||
<defs>
|
||||
<path id="C0_0_3858269516"
|
||||
d="M 0 11.18034 C 2.965061 11.18034 5.80908 10.002309 7.905694 7.905694 C 10.002309 5.80908 11.18034 2.965061 11.18034 -0 C 11.18034 -2.965061 10.002309 -5.80908 7.905694 -7.905694 C 5.80908 -10.002309 2.965061 -11.18034 0 -11.18034 C -2.965061 -11.18034 -5.80908 -10.002309 -7.905694 -7.905694 C -10.002309 -5.80908 -11.18034 -2.965061 -11.18034 0 C -11.18034 2.965061 -10.002309 5.80908 -7.905694 7.905694 C -5.80908 10.002309 -2.965061 11.18034 0 11.18034 z " />
|
||||
</defs>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-0" onclick="(()=>{console.log('node 0')})()"
|
||||
class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="383.475478" y="335.382791" style="fill: #fde2bb" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-1" onclick="(()=>{console.log('node 1')})()"
|
||||
class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="393.562573" y="295.917472" style="fill: #fdba68" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-2" onclick="(()=>{console.log('node 2')})()"
|
||||
class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="395.592267" y="184.349842" style="fill: #fbe9cf" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-3" onclick="(()=>{console.log('node 3')})()"
|
||||
class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="166.614267" y="246.553188" style="fill: #7e70ab" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-4" onclick="(()=>{console.log('node 4')})()"
|
||||
class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="362.886037" y="395.352171" style="fill: #e8e9f1" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-5" onclick="(()=>{console.log('node 5')})()"
|
||||
class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="291.699254" y="114.456198" style="fill: #f9b158" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-6" onclick="(()=>{console.log('node 6')})()"
|
||||
class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="309.72476" y="346.813492" style="fill: #e4e5f0" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-7" onclick="(()=>{console.log('node 7')})()"
|
||||
class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="396.396073" y="371.656412" style="fill: #fdcc8c" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-8" onclick="(()=>{console.log('node 8')})()"
|
||||
class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="311.713" y="188.802087" style="fill: #fedeb3" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-9" onclick="(()=>{console.log('node 9')})()"
|
||||
class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="213.805036" y="285.720019" style="fill: #bab5d7" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-10"
|
||||
onclick="(()=>{console.log('node 10')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="326.464644" y="303.679747" style="fill: #eaebf2" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-11"
|
||||
onclick="(()=>{console.log('node 11')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="468.104517" y="290.196764" style="fill: #f7f7f6" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-12"
|
||||
onclick="(()=>{console.log('node 12')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="169.41455" y="268.66905" style="fill: #dfe1ee" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-13"
|
||||
onclick="(()=>{console.log('node 13')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="252.522958" y="107.607273" style="fill: #eff0f4" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-14"
|
||||
onclick="(()=>{console.log('node 14')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="241.817" y="158.353487" style="fill: #e58a20" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-15"
|
||||
onclick="(()=>{console.log('node 15')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="278.840744" y="190.572938" style="fill: #fedbac" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-16"
|
||||
onclick="(()=>{console.log('node 16')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="190.32114" y="223.314542" style="fill: #dfe1ee" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-17"
|
||||
onclick="(()=>{console.log('node 17')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="233.41271" y="348.401671" style="fill: #c3c0dd" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-18"
|
||||
onclick="(()=>{console.log('node 18')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="122.295483" y="352.502553" style="fill: #fed8a6" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-19"
|
||||
onclick="(()=>{console.log('node 19')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="158.624602" y="400.46174" style="fill: #f7f6f3" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-20"
|
||||
onclick="(()=>{console.log('node 20')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="214.405523" y="244.575019" style="fill: #f9f2e9" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-21"
|
||||
onclick="(()=>{console.log('node 21')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="264.569363" y="223.030096" style="fill: #faecd7" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-22"
|
||||
onclick="(()=>{console.log('node 22')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="220.79649" y="394.869471" style="fill: #fbead2" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-23"
|
||||
onclick="(()=>{console.log('node 23')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="344.302973" y="166.290216" style="fill: #feddaf" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-24"
|
||||
onclick="(()=>{console.log('node 24')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="241.321249" y="255.242558" style="fill: #c3c0dd" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-25"
|
||||
onclick="(()=>{console.log('node 25')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="257.120877" y="296.156882" style="fill: #f9f0e4" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-26"
|
||||
onclick="(()=>{console.log('node 26')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="207.563253" y="203.013335" style="fill: #fbebd5" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-27"
|
||||
onclick="(()=>{console.log('node 27')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="453.314054" y="329.209099" style="fill: #fdc47b" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-28"
|
||||
onclick="(()=>{console.log('node 28')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="350.123561" y="336.312105" style="fill: #fbe9cf" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-29"
|
||||
onclick="(()=>{console.log('node 29')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="287.180764" y="309.56402" style="fill: #f7f6f3" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-30"
|
||||
onclick="(()=>{console.log('node 30')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="287.429936" y="148.935339" style="fill: #fbebd5" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-31"
|
||||
onclick="(()=>{console.log('node 31')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="281.878613" y="277.846944" style="fill: #d1d1e6" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-32"
|
||||
onclick="(()=>{console.log('node 32')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="300.632415" y="433.812968" style="fill: #fde2bb" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-33"
|
||||
onclick="(()=>{console.log('node 33')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="216.196468" y="317.113868" style="fill: #dddfed" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-34"
|
||||
onclick="(()=>{console.log('node 34')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="419.504487" y="334.14189" style="fill: #fdc57f" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-35"
|
||||
onclick="(()=>{console.log('node 35')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="321.071206" y="134.027026" style="fill: #fee0b6" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-36"
|
||||
onclick="(()=>{console.log('node 36')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="366.514998" y="474.152727" style="fill: #fdbd6e" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-37"
|
||||
onclick="(()=>{console.log('node 37')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="208.453065" y="361.465389" style="fill: #cccbe3" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-38"
|
||||
onclick="(()=>{console.log('node 38')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="236.649711" y="206.251683" style="fill: #faecd7" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-39"
|
||||
onclick="(()=>{console.log('node 39')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="298.808991" y="236.296491" style="fill: #fdc57f" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-40"
|
||||
onclick="(()=>{console.log('node 40')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="181.944484" y="318.835753" style="fill: #f9f0e4" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-41"
|
||||
onclick="(()=>{console.log('node 41')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="367.134249" y="434.454954" style="fill: #f6f6f7" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-42"
|
||||
onclick="(()=>{console.log('node 42')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="422.276969" y="403.842356" style="fill: #fdbf72" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-43"
|
||||
onclick="(()=>{console.log('node 43')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="321.091057" y="403.95329" style="fill: #f8f5f1" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-44"
|
||||
onclick="(()=>{console.log('node 44')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="162.445269" y="355.484449" style="fill: #eaebf2" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-45"
|
||||
onclick="(()=>{console.log('node 45')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="341.073251" y="272.287852" style="fill: #f6aa4f" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-46"
|
||||
onclick="(()=>{console.log('node 46')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="389.299516" y="416.267064" style="fill: #de8013" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-47"
|
||||
onclick="(()=>{console.log('node 47')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="213.931911" y="434.927829" style="fill: #fbb55e" />
|
||||
</g>
|
||||
<g clip-path="url(#pd42c8a995e)" id="beatrice-node-male-48"
|
||||
onclick="(()=>{console.log('node 48')})()" class="beatrice-node-pointer">
|
||||
<use xlink:href="#C0_0_3858269516" x="436.061109" y="363.566053" style="fill: #ebecf3" />
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-0" onclick="(()=>{console.log('text 0 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(379.30079 338.694041) scale(0.12 -0.12)">
|
||||
<defs>
|
||||
<path id="DejaVuSans-Bold-31"
|
||||
d="M 750 831 L 1813 831 L 1813 3847 L 722 3622 L 722 4441 L 1806 4666 L 2950 4666 L 2950 831 L 4013 831 L 4013 0 L 750 0 L 750 831 z "
|
||||
transform="scale(0.015625)" />
|
||||
</defs>
|
||||
<use xlink:href="#DejaVuSans-Bold-31" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-1" onclick="(()=>{console.log('text 1 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(389.387885 299.228722) scale(0.12 -0.12)">
|
||||
<defs>
|
||||
<path id="DejaVuSans-Bold-33"
|
||||
d="M 2981 2516 Q 3453 2394 3698 2092 Q 3944 1791 3944 1325 Q 3944 631 3412 270 Q 2881 -91 1863 -91 Q 1503 -91 1142 -33 Q 781 25 428 141 L 428 1069 Q 766 900 1098 814 Q 1431 728 1753 728 Q 2231 728 2486 893 Q 2741 1059 2741 1369 Q 2741 1688 2480 1852 Q 2219 2016 1709 2016 L 1228 2016 L 1228 2791 L 1734 2791 Q 2188 2791 2409 2933 Q 2631 3075 2631 3366 Q 2631 3634 2415 3781 Q 2200 3928 1806 3928 Q 1516 3928 1219 3862 Q 922 3797 628 3669 L 628 4550 Q 984 4650 1334 4700 Q 1684 4750 2022 4750 Q 2931 4750 3382 4451 Q 3834 4153 3834 3553 Q 3834 3144 3618 2883 Q 3403 2622 2981 2516 z "
|
||||
transform="scale(0.015625)" />
|
||||
</defs>
|
||||
<use xlink:href="#DejaVuSans-Bold-33" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-2" onclick="(()=>{console.log('text 2 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(391.41758 187.661092) scale(0.12 -0.12)">
|
||||
<defs>
|
||||
<path id="DejaVuSans-Bold-35"
|
||||
d="M 678 4666 L 3669 4666 L 3669 3781 L 1638 3781 L 1638 3059 Q 1775 3097 1914 3117 Q 2053 3138 2203 3138 Q 3056 3138 3531 2711 Q 4006 2284 4006 1522 Q 4006 766 3489 337 Q 2972 -91 2053 -91 Q 1656 -91 1267 -14 Q 878 63 494 219 L 494 1166 Q 875 947 1217 837 Q 1559 728 1863 728 Q 2300 728 2551 942 Q 2803 1156 2803 1522 Q 2803 1891 2551 2103 Q 2300 2316 1863 2316 Q 1603 2316 1309 2248 Q 1016 2181 678 2041 L 678 4666 z "
|
||||
transform="scale(0.015625)" />
|
||||
</defs>
|
||||
<use xlink:href="#DejaVuSans-Bold-35" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-3" onclick="(()=>{console.log('text 3 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(162.43958 249.864438) scale(0.12 -0.12)">
|
||||
<defs>
|
||||
<path id="DejaVuSans-Bold-36"
|
||||
d="M 2316 2303 Q 2000 2303 1842 2098 Q 1684 1894 1684 1484 Q 1684 1075 1842 870 Q 2000 666 2316 666 Q 2634 666 2792 870 Q 2950 1075 2950 1484 Q 2950 1894 2792 2098 Q 2634 2303 2316 2303 z M 3803 4544 L 3803 3681 Q 3506 3822 3243 3889 Q 2981 3956 2731 3956 Q 2194 3956 1894 3657 Q 1594 3359 1544 2772 Q 1750 2925 1990 3001 Q 2231 3078 2516 3078 Q 3231 3078 3670 2659 Q 4109 2241 4109 1563 Q 4109 813 3618 361 Q 3128 -91 2303 -91 Q 1394 -91 895 523 Q 397 1138 397 2266 Q 397 3422 980 4083 Q 1563 4744 2578 4744 Q 2900 4744 3203 4694 Q 3506 4644 3803 4544 z "
|
||||
transform="scale(0.015625)" />
|
||||
</defs>
|
||||
<use xlink:href="#DejaVuSans-Bold-36" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-4" onclick="(()=>{console.log('text 4 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(358.71135 398.663421) scale(0.12 -0.12)">
|
||||
<defs>
|
||||
<path id="DejaVuSans-Bold-39"
|
||||
d="M 641 103 L 641 966 Q 928 831 1190 764 Q 1453 697 1709 697 Q 2247 697 2547 995 Q 2847 1294 2900 1881 Q 2688 1725 2447 1647 Q 2206 1569 1925 1569 Q 1209 1569 770 1986 Q 331 2403 331 3084 Q 331 3838 820 4291 Q 1309 4744 2131 4744 Q 3044 4744 3544 4128 Q 4044 3513 4044 2388 Q 4044 1231 3459 570 Q 2875 -91 1856 -91 Q 1528 -91 1228 -42 Q 928 6 641 103 z M 2125 2350 Q 2441 2350 2600 2554 Q 2759 2759 2759 3169 Q 2759 3575 2600 3781 Q 2441 3988 2125 3988 Q 1809 3988 1650 3781 Q 1491 3575 1491 3169 Q 1491 2759 1650 2554 Q 1809 2350 2125 2350 z "
|
||||
transform="scale(0.015625)" />
|
||||
</defs>
|
||||
<use xlink:href="#DejaVuSans-Bold-39" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-5" onclick="(()=>{console.log('text 5 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(283.349879 117.767448) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-31" />
|
||||
<use xlink:href="#DejaVuSans-Bold-31" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-6" onclick="(()=>{console.log('text 6 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(301.375385 350.124742) scale(0.12 -0.12)">
|
||||
<defs>
|
||||
<path id="DejaVuSans-Bold-32"
|
||||
d="M 1844 884 L 3897 884 L 3897 0 L 506 0 L 506 884 L 2209 2388 Q 2438 2594 2547 2791 Q 2656 2988 2656 3200 Q 2656 3528 2436 3728 Q 2216 3928 1850 3928 Q 1569 3928 1234 3808 Q 900 3688 519 3450 L 519 4475 Q 925 4609 1322 4679 Q 1719 4750 2100 4750 Q 2938 4750 3402 4381 Q 3866 4013 3866 3353 Q 3866 2972 3669 2642 Q 3472 2313 2841 1759 L 1844 884 z "
|
||||
transform="scale(0.015625)" />
|
||||
</defs>
|
||||
<use xlink:href="#DejaVuSans-Bold-31" />
|
||||
<use xlink:href="#DejaVuSans-Bold-32" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-7" onclick="(()=>{console.log('text 7 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(388.046698 374.967662) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-31" />
|
||||
<use xlink:href="#DejaVuSans-Bold-33" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-8" onclick="(()=>{console.log('text 8 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(303.363625 192.113337) scale(0.12 -0.12)">
|
||||
<defs>
|
||||
<path id="DejaVuSans-Bold-30"
|
||||
d="M 2944 2338 Q 2944 3213 2780 3570 Q 2616 3928 2228 3928 Q 1841 3928 1675 3570 Q 1509 3213 1509 2338 Q 1509 1453 1675 1090 Q 1841 728 2228 728 Q 2613 728 2778 1090 Q 2944 1453 2944 2338 z M 4147 2328 Q 4147 1169 3647 539 Q 3147 -91 2228 -91 Q 1306 -91 806 539 Q 306 1169 306 2328 Q 306 3491 806 4120 Q 1306 4750 2228 4750 Q 3147 4750 3647 4120 Q 4147 3491 4147 2328 z "
|
||||
transform="scale(0.015625)" />
|
||||
</defs>
|
||||
<use xlink:href="#DejaVuSans-Bold-32" />
|
||||
<use xlink:href="#DejaVuSans-Bold-30" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-9" onclick="(()=>{console.log('text 9 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(205.455661 289.031269) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-32" />
|
||||
<use xlink:href="#DejaVuSans-Bold-31" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-10" onclick="(()=>{console.log('text 10 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(318.115269 306.990997) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-32" />
|
||||
<use xlink:href="#DejaVuSans-Bold-32" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-11" onclick="(()=>{console.log('text 11 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(459.755142 293.508014) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-32" />
|
||||
<use xlink:href="#DejaVuSans-Bold-33" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-12" onclick="(()=>{console.log('text 12 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(161.065175 271.9803) scale(0.12 -0.12)">
|
||||
<defs>
|
||||
<path id="DejaVuSans-Bold-38"
|
||||
d="M 2228 2088 Q 1891 2088 1709 1903 Q 1528 1719 1528 1375 Q 1528 1031 1709 848 Q 1891 666 2228 666 Q 2563 666 2741 848 Q 2919 1031 2919 1375 Q 2919 1722 2741 1905 Q 2563 2088 2228 2088 z M 1350 2484 Q 925 2613 709 2878 Q 494 3144 494 3541 Q 494 4131 934 4440 Q 1375 4750 2228 4750 Q 3075 4750 3515 4442 Q 3956 4134 3956 3541 Q 3956 3144 3739 2878 Q 3522 2613 3097 2484 Q 3572 2353 3814 2058 Q 4056 1763 4056 1313 Q 4056 619 3595 264 Q 3134 -91 2228 -91 Q 1319 -91 855 264 Q 391 619 391 1313 Q 391 1763 633 2058 Q 875 2353 1350 2484 z M 1631 3419 Q 1631 3141 1786 2991 Q 1941 2841 2228 2841 Q 2509 2841 2662 2991 Q 2816 3141 2816 3419 Q 2816 3697 2662 3845 Q 2509 3994 2228 3994 Q 1941 3994 1786 3844 Q 1631 3694 1631 3419 z "
|
||||
transform="scale(0.015625)" />
|
||||
</defs>
|
||||
<use xlink:href="#DejaVuSans-Bold-32" />
|
||||
<use xlink:href="#DejaVuSans-Bold-38" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-13" onclick="(()=>{console.log('text 13 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(244.173583 110.918523) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-33" />
|
||||
<use xlink:href="#DejaVuSans-Bold-31" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-14" onclick="(()=>{console.log('text 14 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(233.467625 161.664737) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-33" />
|
||||
<use xlink:href="#DejaVuSans-Bold-32" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-15" onclick="(()=>{console.log('text 15 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(270.491369 193.884188) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-33" />
|
||||
<use xlink:href="#DejaVuSans-Bold-33" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-16" onclick="(()=>{console.log('text 16 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(181.971765 226.625792) scale(0.12 -0.12)">
|
||||
<defs>
|
||||
<path id="DejaVuSans-Bold-34"
|
||||
d="M 2356 3675 L 1038 1722 L 2356 1722 L 2356 3675 z M 2156 4666 L 3494 4666 L 3494 1722 L 4159 1722 L 4159 850 L 3494 850 L 3494 0 L 2356 0 L 2356 850 L 288 850 L 288 1881 L 2156 4666 z "
|
||||
transform="scale(0.015625)" />
|
||||
</defs>
|
||||
<use xlink:href="#DejaVuSans-Bold-33" />
|
||||
<use xlink:href="#DejaVuSans-Bold-34" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-17" onclick="(()=>{console.log('text 17 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(225.063335 351.712921) scale(0.12 -0.12)">
|
||||
<defs>
|
||||
<path id="DejaVuSans-Bold-37"
|
||||
d="M 428 4666 L 3944 4666 L 3944 3988 L 2125 0 L 953 0 L 2675 3781 L 428 3781 L 428 4666 z "
|
||||
transform="scale(0.015625)" />
|
||||
</defs>
|
||||
<use xlink:href="#DejaVuSans-Bold-33" />
|
||||
<use xlink:href="#DejaVuSans-Bold-37" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-18" onclick="(()=>{console.log('text 18 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(113.946108 355.813803) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-34" />
|
||||
<use xlink:href="#DejaVuSans-Bold-31" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-19" onclick="(()=>{console.log('text 19 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(150.275227 403.77299) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-34" />
|
||||
<use xlink:href="#DejaVuSans-Bold-32" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-20" onclick="(()=>{console.log('text 20 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(206.056148 247.886269) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-34" />
|
||||
<use xlink:href="#DejaVuSans-Bold-34" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-21" onclick="(()=>{console.log('text 21 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(256.219988 226.341346) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-34" />
|
||||
<use xlink:href="#DejaVuSans-Bold-35" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-22" onclick="(()=>{console.log('text 22 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(212.447115 398.180721) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-34" />
|
||||
<use xlink:href="#DejaVuSans-Bold-36" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-23" onclick="(()=>{console.log('text 23 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(335.953598 169.601466) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-34" />
|
||||
<use xlink:href="#DejaVuSans-Bold-37" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-24" onclick="(()=>{console.log('text 24 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(232.971874 258.553808) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-34" />
|
||||
<use xlink:href="#DejaVuSans-Bold-38" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-25" onclick="(()=>{console.log('text 25 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(248.771502 299.468132) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-34" />
|
||||
<use xlink:href="#DejaVuSans-Bold-39" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-26" onclick="(()=>{console.log('text 26 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(199.213878 206.324585) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-35" />
|
||||
<use xlink:href="#DejaVuSans-Bold-30" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-27" onclick="(()=>{console.log('text 27 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(444.964679 332.520349) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-35" />
|
||||
<use xlink:href="#DejaVuSans-Bold-32" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-28" onclick="(()=>{console.log('text 28 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(341.774186 339.623355) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-35" />
|
||||
<use xlink:href="#DejaVuSans-Bold-34" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-29" onclick="(()=>{console.log('text 29 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(278.831389 312.87527) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-36" />
|
||||
<use xlink:href="#DejaVuSans-Bold-38" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-30" onclick="(()=>{console.log('text 30 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(279.080561 152.246589) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-37" />
|
||||
<use xlink:href="#DejaVuSans-Bold-30" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-31" onclick="(()=>{console.log('text 31 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(273.529238 281.158194) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-37" />
|
||||
<use xlink:href="#DejaVuSans-Bold-31" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-32" onclick="(()=>{console.log('text 32 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(292.28304 437.124218) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-37" />
|
||||
<use xlink:href="#DejaVuSans-Bold-33" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-33" onclick="(()=>{console.log('text 33 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(207.847093 320.425118) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-37" />
|
||||
<use xlink:href="#DejaVuSans-Bold-34" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-34" onclick="(()=>{console.log('text 34 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(411.155112 337.45314) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-37" />
|
||||
<use xlink:href="#DejaVuSans-Bold-35" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-35" onclick="(()=>{console.log('text 35 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(312.721831 137.338276) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-37" />
|
||||
<use xlink:href="#DejaVuSans-Bold-36" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-36" onclick="(()=>{console.log('text 36 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(358.165623 477.463977) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-37" />
|
||||
<use xlink:href="#DejaVuSans-Bold-37" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-37" onclick="(()=>{console.log('text 37 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(200.10369 364.776639) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-37" />
|
||||
<use xlink:href="#DejaVuSans-Bold-38" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-38" onclick="(()=>{console.log('text 38 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(228.300336 209.562933) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-37" />
|
||||
<use xlink:href="#DejaVuSans-Bold-39" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-39" onclick="(()=>{console.log('text 39 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(290.459616 239.607741) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-38" />
|
||||
<use xlink:href="#DejaVuSans-Bold-30" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-40" onclick="(()=>{console.log('text 40 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(173.595109 322.147003) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-38" />
|
||||
<use xlink:href="#DejaVuSans-Bold-31" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-41" onclick="(()=>{console.log('text 41 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(358.784874 437.766204) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-38" />
|
||||
<use xlink:href="#DejaVuSans-Bold-36" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-42" onclick="(()=>{console.log('text 42 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(413.927594 407.153606) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-38" />
|
||||
<use xlink:href="#DejaVuSans-Bold-37" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-43" onclick="(()=>{console.log('text 43 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(312.741682 407.26454) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-38" />
|
||||
<use xlink:href="#DejaVuSans-Bold-38" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-44" onclick="(()=>{console.log('text 44 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(154.095894 358.795699) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-38" />
|
||||
<use xlink:href="#DejaVuSans-Bold-39" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-45" onclick="(()=>{console.log('text 45 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(332.723876 275.599102) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-39" />
|
||||
<use xlink:href="#DejaVuSans-Bold-37" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-46" onclick="(()=>{console.log('text 46 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(380.950141 419.578314) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-39" />
|
||||
<use xlink:href="#DejaVuSans-Bold-38" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-47" onclick="(()=>{console.log('text 47 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(205.582536 438.239079) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-39" />
|
||||
<use xlink:href="#DejaVuSans-Bold-39" x="69.580078" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beatrice-text-male-48" onclick="(()=>{console.log('text 48 clicked')})()"
|
||||
class="beatrice-text-pointer">
|
||||
<g clip-path="url(#pd42c8a995e)">
|
||||
|
||||
<g transform="translate(423.537047 366.877303) scale(0.12 -0.12)">
|
||||
<use xlink:href="#DejaVuSans-Bold-31" />
|
||||
<use xlink:href="#DejaVuSans-Bold-30" x="69.580078" />
|
||||
<use xlink:href="#DejaVuSans-Bold-30" x="139.160156" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="pd42c8a995e">
|
||||
<rect x="85.985534" y="69.12" width="418.428931" height="443.52" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 54 KiB |
BIN
client/demo/public/assets/buymeacoffee.png
Normal file
After Width: | Height: | Size: 12 KiB |
30
client/demo/public/assets/gui_settings/GUI.json
Normal file
@ -0,0 +1,30 @@
|
||||
{
|
||||
"type": "demo",
|
||||
"id": "RVC",
|
||||
"front": {
|
||||
"modelSlotControl": [
|
||||
{
|
||||
"name": "headerArea",
|
||||
"options": {
|
||||
"mainTitle": "Realtime Voice Changer Client",
|
||||
"subTitle": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "modelSlotArea",
|
||||
"options": {}
|
||||
},
|
||||
{
|
||||
"name": "characterArea",
|
||||
"options": {}
|
||||
},
|
||||
{
|
||||
"name": "configArea",
|
||||
"options": {
|
||||
"detectors": ["dio", "harvest", "crepe", "crepe_full", "crepe_tiny", "rmvpe", "rmvpe_onnx", "fcpe"],
|
||||
"inputChunkNums": [1, 2, 4, 6, 8, 16, 24, 32, 40, 48, 64, 80, 96, 112, 128, 192, 256, 320, 384, 448, 512, 576, 640, 704, 768, 832, 896, 960, 1024, 2048, 4096, 8192, 16384]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
30
client/demo/public/assets/gui_settings/RVC.json
Normal file
@ -0,0 +1,30 @@
|
||||
{
|
||||
"type": "demo",
|
||||
"id": "RVC",
|
||||
"front": {
|
||||
"modelSlotControl": [
|
||||
{
|
||||
"name": "headerArea",
|
||||
"options": {
|
||||
"mainTitle": "Realtime Voice Changer Client",
|
||||
"subTitle": "for RVC"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "modelSlotArea",
|
||||
"options": {}
|
||||
},
|
||||
{
|
||||
"name": "characterArea",
|
||||
"options": {}
|
||||
},
|
||||
{
|
||||
"name": "configArea",
|
||||
"options": {
|
||||
"detectors": ["dio", "harvest", "crepe"],
|
||||
"inputChunkNums": [8, 16, 24, 32, 40, 48, 64, 80, 96, 112, 128, 192, 256, 320, 384, 448, 512, 576, 640, 704, 768, 832, 896, 960, 1024, 2048]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
0
client/demo/public/assets/gui_settings/edition.txt
Normal file
1
client/demo/public/assets/gui_settings/edition_dml.txt
Normal file
@ -0,0 +1 @@
|
||||
onnxdirectML-cuda
|
1
client/demo/public/assets/gui_settings/edition_web.txt
Normal file
@ -0,0 +1 @@
|
||||
web
|
1
client/demo/public/assets/gui_settings/version.txt
Normal file
@ -0,0 +1 @@
|
||||
-.-.-.-
|
BIN
client/demo/public/assets/icons/blank.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
1
client/demo/public/assets/icons/folder.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-folder"><path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"></path></svg>
|
After Width: | Height: | Size: 311 B |
BIN
client/demo/public/assets/icons/human.png
Normal file
After Width: | Height: | Size: 26 KiB |
BIN
client/demo/public/assets/icons/noimage.png
Normal file
After Width: | Height: | Size: 2.1 KiB |
1
client/demo/public/assets/icons/tool.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-tool"><path d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z"></path></svg>
|
After Width: | Height: | Size: 386 B |
1
client/demo/public/info_web
Normal file
@ -0,0 +1 @@
|
||||
{}
|
BIN
client/demo/public/settings/amitaro/image.psd
Normal file
40
client/demo/public/settings/amitaro/motion.json
Normal file
@ -0,0 +1,40 @@
|
||||
[
|
||||
{ "mode": "normal", "z_index": 0, "number": 1, "layer_path": "ROOT_全身" },
|
||||
{ "mode": "normal", "z_index": 1, "number": 50, "layer_path": "ROOT_!目_*通常" },
|
||||
{ "mode": "normal", "z_index": 1, "number": 1, "layer_path": "ROOT_!目_*通常→" },
|
||||
{ "mode": "normal", "z_index": 1, "number": 1, "layer_path": "ROOT_!目_*微笑" },
|
||||
{ "mode": "normal", "z_index": 1, "number": 1, "layer_path": "ROOT_!目_*∩∩" },
|
||||
{ "mode": "normal", "z_index": 1, "number": 1, "layer_path": "ROOT_!目_*微笑" },
|
||||
{ "mode": "normal", "z_index": 2, "number": 80, "layer_path": "ROOT_!口_*にこ" },
|
||||
{ "mode": "normal", "z_index": 2, "number": 10, "layer_path": "ROOT_!口_*おすまし" },
|
||||
{ "mode": "normal", "z_index": 3, "number": 100, "layer_path": "ROOT_!眉_*平行" },
|
||||
{ "mode": "normal", "z_index": 3, "number": 100, "layer_path": "ROOT_!眉_*通常" },
|
||||
{ "mode": "normal", "z_index": 4, "number": 100, "layer_path": "ROOT_表情_なし" },
|
||||
{ "mode": "normal", "z_index": 4, "number": 100, "layer_path": "ROOT_表情_赤面" },
|
||||
{ "mode": "normal", "z_index": 5, "number": 100, "layer_path": "ROOT_漫符_なし" },
|
||||
|
||||
{ "mode": "talking", "z_index": 0, "number": 1, "layer_path": "ROOT_全身" },
|
||||
{ "mode": "talking", "z_index": 1, "number": 50, "layer_path": "ROOT_!目_*通常" },
|
||||
{ "mode": "talking", "z_index": 1, "number": 1, "layer_path": "ROOT_!目_*通常→" },
|
||||
{ "mode": "talking", "z_index": 1, "number": 1, "layer_path": "ROOT_!目_*微笑" },
|
||||
{ "mode": "talking", "z_index": 1, "number": 1, "layer_path": "ROOT_!目_*∩∩" },
|
||||
{ "mode": "talking", "z_index": 1, "number": 1, "layer_path": "ROOT_!目_*微笑" },
|
||||
{ "mode": "talking", "z_index": 2, "number": 10, "layer_path": "ROOT_!口_*お" },
|
||||
{ "mode": "talking", "z_index": 2, "number": 5, "layer_path": "ROOT_!口_*え" },
|
||||
{ "mode": "talking", "z_index": 2, "number": 10, "layer_path": "ROOT_!口_* -" },
|
||||
{ "mode": "talking", "z_index": 2, "number": 5, "layer_path": "ROOT_!口_*う" },
|
||||
{ "mode": "talking", "z_index": 2, "number": 10, "layer_path": "ROOT_!口_*にこ" },
|
||||
{ "mode": "talking", "z_index": 3, "number": 20, "layer_path": "ROOT_!眉_*平行" },
|
||||
{ "mode": "talking", "z_index": 3, "number": 40, "layer_path": "ROOT_!眉_*通常" },
|
||||
{ "mode": "talking", "z_index": 3, "number": 40, "layer_path": "ROOT_!眉_*ドヤ" },
|
||||
{ "mode": "talking", "z_index": 4, "number": 20, "layer_path": "ROOT_表情_なし" },
|
||||
{ "mode": "talking", "z_index": 4, "number": 100, "layer_path": "ROOT_表情_赤面" },
|
||||
{ "mode": "talking", "z_index": 5, "number": 10, "layer_path": "ROOT_漫符_なし" },
|
||||
{ "mode": "talking", "z_index": 5, "number": 100, "layer_path": "ROOT_漫符_*♪" },
|
||||
{ "mode": "talking", "z_index": 0, "number": 1, "layer_path": "ROOT_全身" },
|
||||
{ "mode": "talking", "z_index": 1, "number": 1, "layer_path": "ROOT_!目_*∪∪" },
|
||||
{ "mode": "talking", "z_index": 2, "number": 1, "layer_path": "ROOT_!口_*え" },
|
||||
{ "mode": "talking", "z_index": 3, "number": 1, "layer_path": "ROOT_!眉_*平行" },
|
||||
{ "mode": "talking", "z_index": 4, "number": 1, "layer_path": "ROOT_表情_なし" },
|
||||
{ "mode": "talking", "z_index": 5, "number": 1, "layer_path": "ROOT_漫符_なし" }
|
||||
]
|
6
client/demo/public/settings/amitaro/settings.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"charaName": "あみたろ",
|
||||
"psdFile": "/assets/settings/image.psd",
|
||||
"motionFile": "/assets/settings/motion.json",
|
||||
"motionSpeedRate": 1
|
||||
}
|
BIN
client/demo/public/settings/image.psd
Normal file
BIN
client/demo/public/settings/kikotokurage/image.psd
Normal file
14
client/demo/public/settings/kikotokurage/motion.json
Normal file
@ -0,0 +1,14 @@
|
||||
[
|
||||
{ "mode": "normal", "z_index": 0, "number": 40, "layer_path": "ROOT_normal2" },
|
||||
{ "mode": "normal", "z_index": 0, "number": 100, "layer_path": "ROOT_normal3" },
|
||||
|
||||
{ "mode": "talking", "z_index": 0, "number": 5, "layer_path": "ROOT_talk2" },
|
||||
{ "mode": "talking", "z_index": 0, "number": 10, "layer_path": "ROOT_talk1" },
|
||||
{ "mode": "talking", "z_index": 0, "number": 11, "layer_path": "ROOT_talk-u2" },
|
||||
{ "mode": "talking", "z_index": 0, "number": 11, "layer_path": "ROOT_talk-u1" },
|
||||
{ "mode": "talking", "z_index": 0, "number": 11, "layer_path": "ROOT_talk-u3" },
|
||||
{ "mode": "talking", "z_index": 0, "number": 11, "layer_path": "ROOT_talk-u1" },
|
||||
{ "mode": "talking", "z_index": 0, "number": 11, "layer_path": "ROOT_talk-u2" },
|
||||
{ "mode": "talking", "z_index": 0, "number": 11, "layer_path": "ROOT_talk-u1" },
|
||||
{ "mode": "talking", "z_index": 0, "number": 4, "layer_path": "ROOT_talk-u4" }
|
||||
]
|
6
client/demo/public/settings/kikotokurage/settings.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"charaName": "黄琴海月",
|
||||
"psdFile": "/assets/settings/image.psd",
|
||||
"motionFile": "/assets/settings/motion.json",
|
||||
"motionSpeedRate": 1
|
||||
}
|
BIN
client/demo/public/settings/kikotomahiro/image.psd
Normal file
4
client/demo/public/settings/kikotomahiro/motion.json
Normal file
@ -0,0 +1,4 @@
|
||||
[
|
||||
{ "mode": "normal", "z_index": 0, "number": 10, "layer_path": "ROOT_レイヤー2" },
|
||||
{ "mode": "talking", "z_index": 0, "number": 10, "layer_path": "ROOT_レイヤー1" }
|
||||
]
|
6
client/demo/public/settings/kikotomahiro/settings.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"charaName": "黄琴まひろ",
|
||||
"psdFile": "/assets/settings/image.psd",
|
||||
"motionFile": "/assets/settings/motion.json",
|
||||
"motionSpeedRate": 4
|
||||
}
|
40
client/demo/public/settings/motion.json
Normal file
@ -0,0 +1,40 @@
|
||||
[
|
||||
{ "mode": "normal", "z_index": 0, "number": 1, "layer_path": "ROOT_全身" },
|
||||
{ "mode": "normal", "z_index": 1, "number": 50, "layer_path": "ROOT_!目_*通常" },
|
||||
{ "mode": "normal", "z_index": 1, "number": 1, "layer_path": "ROOT_!目_*通常→" },
|
||||
{ "mode": "normal", "z_index": 1, "number": 1, "layer_path": "ROOT_!目_*微笑" },
|
||||
{ "mode": "normal", "z_index": 1, "number": 1, "layer_path": "ROOT_!目_*∩∩" },
|
||||
{ "mode": "normal", "z_index": 1, "number": 1, "layer_path": "ROOT_!目_*微笑" },
|
||||
{ "mode": "normal", "z_index": 2, "number": 80, "layer_path": "ROOT_!口_*にこ" },
|
||||
{ "mode": "normal", "z_index": 2, "number": 10, "layer_path": "ROOT_!口_*おすまし" },
|
||||
{ "mode": "normal", "z_index": 3, "number": 100, "layer_path": "ROOT_!眉_*平行" },
|
||||
{ "mode": "normal", "z_index": 3, "number": 100, "layer_path": "ROOT_!眉_*通常" },
|
||||
{ "mode": "normal", "z_index": 4, "number": 100, "layer_path": "ROOT_表情_なし" },
|
||||
{ "mode": "normal", "z_index": 4, "number": 100, "layer_path": "ROOT_表情_赤面" },
|
||||
{ "mode": "normal", "z_index": 5, "number": 100, "layer_path": "ROOT_漫符_なし" },
|
||||
|
||||
{ "mode": "talking", "z_index": 0, "number": 1, "layer_path": "ROOT_全身" },
|
||||
{ "mode": "talking", "z_index": 1, "number": 50, "layer_path": "ROOT_!目_*通常" },
|
||||
{ "mode": "talking", "z_index": 1, "number": 1, "layer_path": "ROOT_!目_*通常→" },
|
||||
{ "mode": "talking", "z_index": 1, "number": 1, "layer_path": "ROOT_!目_*微笑" },
|
||||
{ "mode": "talking", "z_index": 1, "number": 1, "layer_path": "ROOT_!目_*∩∩" },
|
||||
{ "mode": "talking", "z_index": 1, "number": 1, "layer_path": "ROOT_!目_*微笑" },
|
||||
{ "mode": "talking", "z_index": 2, "number": 10, "layer_path": "ROOT_!口_*お" },
|
||||
{ "mode": "talking", "z_index": 2, "number": 5, "layer_path": "ROOT_!口_*え" },
|
||||
{ "mode": "talking", "z_index": 2, "number": 10, "layer_path": "ROOT_!口_* -" },
|
||||
{ "mode": "talking", "z_index": 2, "number": 5, "layer_path": "ROOT_!口_*う" },
|
||||
{ "mode": "talking", "z_index": 2, "number": 10, "layer_path": "ROOT_!口_*にこ" },
|
||||
{ "mode": "talking", "z_index": 3, "number": 20, "layer_path": "ROOT_!眉_*平行" },
|
||||
{ "mode": "talking", "z_index": 3, "number": 40, "layer_path": "ROOT_!眉_*通常" },
|
||||
{ "mode": "talking", "z_index": 3, "number": 40, "layer_path": "ROOT_!眉_*ドヤ" },
|
||||
{ "mode": "talking", "z_index": 4, "number": 20, "layer_path": "ROOT_表情_なし" },
|
||||
{ "mode": "talking", "z_index": 4, "number": 100, "layer_path": "ROOT_表情_赤面" },
|
||||
{ "mode": "talking", "z_index": 5, "number": 10, "layer_path": "ROOT_漫符_なし" },
|
||||
{ "mode": "talking", "z_index": 5, "number": 100, "layer_path": "ROOT_漫符_*♪" },
|
||||
{ "mode": "talking", "z_index": 0, "number": 1, "layer_path": "ROOT_全身" },
|
||||
{ "mode": "talking", "z_index": 1, "number": 1, "layer_path": "ROOT_!目_*∪∪" },
|
||||
{ "mode": "talking", "z_index": 2, "number": 1, "layer_path": "ROOT_!口_*え" },
|
||||
{ "mode": "talking", "z_index": 3, "number": 1, "layer_path": "ROOT_!眉_*平行" },
|
||||
{ "mode": "talking", "z_index": 4, "number": 1, "layer_path": "ROOT_表情_なし" },
|
||||
{ "mode": "talking", "z_index": 5, "number": 1, "layer_path": "ROOT_漫符_なし" }
|
||||
]
|
6
client/demo/public/settings/settings.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"charaName": "あみたろ",
|
||||
"psdFile": "/assets/settings/image.psd",
|
||||
"motionFile": "/assets/settings/motion.json",
|
||||
"motionSpeedRate": 1
|
||||
}
|
BIN
client/demo/public/settings/tsukuyomi/image.psd
Normal file
25
client/demo/public/settings/tsukuyomi/motion.json
Normal file
@ -0,0 +1,25 @@
|
||||
[
|
||||
{ "mode": "normal", "z_index": 0, "number": 10, "layer_path": "ROOT_!体_!体 ※選択肢なし" },
|
||||
{ "mode": "normal", "z_index": 1, "number": 200, "layer_path": "ROOT_!右腕_*右手を下げる" },
|
||||
{ "mode": "normal", "z_index": 1, "number": 40, "layer_path": "ROOT_!右腕_*右手を口に当てる" },
|
||||
{ "mode": "normal", "z_index": 2, "number": 10, "layer_path": "ROOT_!左腕_*左手を下げる" },
|
||||
{ "mode": "normal", "z_index": 3, "number": 10, "layer_path": "ROOT_!髪(おさげ)_!髪(おさげ) ※選択肢なし" },
|
||||
{ "mode": "normal", "z_index": 4, "number": 10, "layer_path": "ROOT_!口 _*口を閉じて微笑む" },
|
||||
{ "mode": "normal", "z_index": 5, "number": 10, "layer_path": "ROOT_!頬 _*通常" },
|
||||
{ "mode": "normal", "z_index": 6, "number": 10, "layer_path": "ROOT_!目_*目を少し細める ★デフォルト" },
|
||||
{ "mode": "normal", "z_index": 7, "number": 100, "layer_path": "ROOT_!眉 _*通常眉" },
|
||||
{ "mode": "normal", "z_index": 7, "number": 10, "layer_path": "ROOT_!眉 _*通常眉:少し下げ" },
|
||||
|
||||
{ "mode": "talking", "z_index": 0, "number": 10, "layer_path": "ROOT_!体_!体 ※選択肢なし" },
|
||||
{ "mode": "talking", "z_index": 1, "number": 200, "layer_path": "ROOT_!右腕_*右手を下げる" },
|
||||
{ "mode": "talking", "z_index": 1, "number": 40, "layer_path": "ROOT_!右腕_*右手を口に当てる" },
|
||||
{ "mode": "talking", "z_index": 2, "number": 10, "layer_path": "ROOT_!左腕_*左手を下げる" },
|
||||
{ "mode": "talking", "z_index": 3, "number": 10, "layer_path": "ROOT_!髪(おさげ)_!髪(おさげ) ※選択肢なし" },
|
||||
{ "mode": "talking", "z_index": 4, "number": 3, "layer_path": "ROOT_!口 _*口を閉じて微笑む" },
|
||||
{ "mode": "talking", "z_index": 4, "number": 3, "layer_path": "ROOT_!口 _*小さく笑う" },
|
||||
{ "mode": "talking", "z_index": 4, "number": 3, "layer_path": "ROOT_!口 _*大きく笑う" },
|
||||
{ "mode": "talking", "z_index": 5, "number": 10, "layer_path": "ROOT_!頬 _*通常" },
|
||||
{ "mode": "talking", "z_index": 6, "number": 10, "layer_path": "ROOT_!目_*目を少し細める ★デフォルト" },
|
||||
{ "mode": "talking", "z_index": 7, "number": 100, "layer_path": "ROOT_!眉 _*通常眉" },
|
||||
{ "mode": "talking", "z_index": 7, "number": 10, "layer_path": "ROOT_!眉 _*通常眉:少し下げ" }
|
||||
]
|
6
client/demo/public/settings/tsukuyomi/settings.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"charaName": "つくよみちゃん",
|
||||
"psdFile": "/assets/settings/image.psd",
|
||||
"motionFile": "/assets/settings/motion.json",
|
||||
"motionSpeedRate": 4
|
||||
}
|
@ -1,67 +1,138 @@
|
||||
import * as React from "react";
|
||||
import { createRoot } from "react-dom/client";
|
||||
import "./css/App.css"
|
||||
import { useMemo, } from "react";
|
||||
import { useMicrophoneOptions } from "./100_options_microphone";
|
||||
import { library } from "@fortawesome/fontawesome-svg-core";
|
||||
import { fas } from "@fortawesome/free-solid-svg-icons";
|
||||
import { far } from "@fortawesome/free-regular-svg-icons";
|
||||
import { fab } from "@fortawesome/free-brands-svg-icons";
|
||||
import { ErrorInfo, useEffect, useMemo, useState } from "react";
|
||||
|
||||
import "./css/App.css";
|
||||
import ErrorBoundary from "./001_provider/900_ErrorBoundary";
|
||||
import { AppStateProvider } from "./001_provider/001_AppStateProvider";
|
||||
import { AppRootProvider, useAppRoot } from "./001_provider/001_AppRootProvider";
|
||||
import { useIndexedDB } from "@dannadori/voice-changer-client-js";
|
||||
import { Demo } from "./components/demo/010_Demo";
|
||||
import { useMessageBuilder } from "./hooks/useMessageBuilder";
|
||||
import { removeDB as webDBRemove } from "@dannadori/voice-changer-js";
|
||||
|
||||
library.add(fas, far, fab);
|
||||
|
||||
const container = document.getElementById("app")!;
|
||||
const root = createRoot(container);
|
||||
|
||||
const App = () => {
|
||||
const { appGuiSettingState } = useAppRoot();
|
||||
const front = useMemo(() => {
|
||||
if (appGuiSettingState.appGuiSetting.type == "demo") {
|
||||
return <Demo></Demo>;
|
||||
} else {
|
||||
return <>unknown gui type. {appGuiSettingState.appGuiSetting.type}</>;
|
||||
}
|
||||
}, [appGuiSettingState.appGuiSetting.type]);
|
||||
|
||||
const { voiceChangerSetting, clearSetting } = useMicrophoneOptions()
|
||||
return <>{front}</>;
|
||||
};
|
||||
|
||||
const onClearSettingClicked = async () => {
|
||||
clearSetting()
|
||||
location.reload()
|
||||
}
|
||||
const AppStateWrapper = () => {
|
||||
const { appGuiSettingState, getGUISetting } = useAppRoot();
|
||||
const messageBuilderState = useMessageBuilder();
|
||||
// エラーメッセージ登録
|
||||
useMemo(() => {
|
||||
messageBuilderState.setMessage(__filename, "Problem", { ja: "ちょっと問題が起きたみたいです。", en: "Looks like there's a bit of a problem." });
|
||||
messageBuilderState.setMessage(__filename, "Problem-sub1", { ja: "このアプリで管理している情報をクリアすると回復する場合があります。", en: "" });
|
||||
messageBuilderState.setMessage(__filename, "Problem-sub2", { ja: "下記のボタンを押して情報をクリアします。", en: "If you clear the information being managed by this app, it may be recoverable." });
|
||||
messageBuilderState.setMessage(__filename, "Problem-action1", { ja: "アプリを初期化", en: "Initialize" });
|
||||
messageBuilderState.setMessage(__filename, "Problem-action2", { ja: "初期化せずリロード", en: "Reload without initialize" });
|
||||
}, []);
|
||||
|
||||
const clearRow = useMemo(() => {
|
||||
// エラーバウンダリー設定
|
||||
const [error, setError] = useState<{ error: Error; errorInfo: ErrorInfo | null; reason: any }>();
|
||||
const { removeDB } = useIndexedDB({ clientType: null });
|
||||
|
||||
const errorComponent = useMemo(() => {
|
||||
const errorName = error?.error.name || "no error name";
|
||||
const errorMessage = error?.error.message || "no error message";
|
||||
const errorInfos = (error?.errorInfo?.componentStack || "no error stack").split("\n");
|
||||
const reasonMessage = (error?.reason || "no reason").toString();
|
||||
const reasonStack = (error?.reason.stack || "no stack").split("\n") as string[];
|
||||
|
||||
const onClearCacheClicked = async () => {
|
||||
await removeDB();
|
||||
await webDBRemove();
|
||||
location.reload();
|
||||
};
|
||||
const onReloadClicked = () => {
|
||||
location.reload();
|
||||
};
|
||||
return (
|
||||
<>
|
||||
<div className="body-row split-3-3-4 left-padding-1">
|
||||
<div className="body-button-container">
|
||||
<div className="body-button" onClick={onClearSettingClicked}>clear setting</div>
|
||||
</div>
|
||||
<div className="body-item-text"></div>
|
||||
<div className="body-item-text"></div>
|
||||
<div className="error-container">
|
||||
<div className="top-error-message">{messageBuilderState.getMessage(__filename, "Problem")}</div>
|
||||
<div className="top-error-description">
|
||||
<p> {messageBuilderState.getMessage(__filename, "Problem-sub1")}</p>
|
||||
<p> {messageBuilderState.getMessage(__filename, "Problem-sub2")}</p>
|
||||
<p>
|
||||
<button onClick={onClearCacheClicked}>{messageBuilderState.getMessage(__filename, "Problem-action1")}</button>
|
||||
</p>
|
||||
<p>
|
||||
<button onClick={onReloadClicked}>{messageBuilderState.getMessage(__filename, "Problem-action2")}</button>
|
||||
</p>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}, [])
|
||||
|
||||
|
||||
return (
|
||||
<div className="main-body">
|
||||
<div className="body-row split-6-4">
|
||||
<div className="body-top-title">
|
||||
Voice Changer Setting
|
||||
<div className="error-detail">
|
||||
<div className="error-name">{errorName}</div>
|
||||
<div className="error-message">{errorMessage}</div>
|
||||
<div className="error-info-container">
|
||||
{errorInfos.map((x) => {
|
||||
return (
|
||||
<div className="error-info-line" key={x}>
|
||||
{x}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
<div className="body-top-title-belongings">
|
||||
<div className="belonging-item">
|
||||
<a className="link" href="https://github.com/w-okada/voice-changer" target="_blank" rel="noopener noreferrer">
|
||||
<img src="./assets/icons/github.svg" />
|
||||
<span>github</span>
|
||||
</a>
|
||||
<div className="error-detail">
|
||||
<div className="error-name">{reasonMessage}</div>
|
||||
<div className="error-message"></div>
|
||||
<div className="error-info-container">
|
||||
{reasonStack.map((x) => {
|
||||
return (
|
||||
<div className="error-info-line" key={x}>
|
||||
{x}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
<div className="belonging-item">
|
||||
<a className="link" href="https://zenn.dev/wok/articles/s01_vc001_top" target="_blank" rel="noopener noreferrer">
|
||||
<img src="./assets/icons/help-circle.svg" />
|
||||
<span>manual</span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
{clearRow}
|
||||
{voiceChangerSetting}
|
||||
<div>
|
||||
<audio id="audio-output"></audio>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
);
|
||||
}, [error]);
|
||||
|
||||
const updateError = (error: Error, errorInfo: React.ErrorInfo | null, reason: any) => {
|
||||
setError({ error, errorInfo, reason });
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const loadDefaultModelType = async () => {
|
||||
getGUISetting();
|
||||
};
|
||||
loadDefaultModelType();
|
||||
}, []);
|
||||
|
||||
if (!appGuiSettingState.guiSettingLoaded) {
|
||||
return <>loading...</>;
|
||||
} else {
|
||||
return (
|
||||
<ErrorBoundary fallback={errorComponent} onError={updateError}>
|
||||
<AppStateProvider>
|
||||
<App></App>
|
||||
</AppStateProvider>
|
||||
</ErrorBoundary>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
root.render(
|
||||
<App></App>
|
||||
<AppRootProvider>
|
||||
<AppStateWrapper></AppStateWrapper>
|
||||
</AppRootProvider>,
|
||||
);
|
||||
|
83
client/demo/src/001_globalHooks/001_useAppGuiSetting.ts
Normal file
@ -0,0 +1,83 @@
|
||||
import { useEffect, useState } from "react"
|
||||
|
||||
export type AppGuiSetting = {
|
||||
type: "demo",
|
||||
front: {
|
||||
"modelSlotControl": GuiComponentSetting[],
|
||||
}
|
||||
}
|
||||
|
||||
export type GuiComponentSetting = {
|
||||
"name": string,
|
||||
"options": any
|
||||
}
|
||||
|
||||
const InitialAppGuiDemoSetting: AppGuiSetting = {
|
||||
type: "demo",
|
||||
front: {
|
||||
"modelSlotControl": []
|
||||
}
|
||||
}
|
||||
|
||||
export type AppGuiSettingState = {
|
||||
appGuiSetting: AppGuiSetting
|
||||
guiSettingLoaded: boolean
|
||||
version: string
|
||||
edition: string
|
||||
}
|
||||
|
||||
export type AppGuiSettingStateAndMethod = AppGuiSettingState & {
|
||||
getAppGuiSetting: (url: string) => Promise<void>
|
||||
clearAppGuiSetting: () => void
|
||||
}
|
||||
|
||||
export const useAppGuiSetting = (): AppGuiSettingStateAndMethod => {
|
||||
const [guiSettingLoaded, setGuiSettingLoaded] = useState<boolean>(false)
|
||||
const [appGuiSetting, setAppGuiSetting] = useState<AppGuiSetting>(InitialAppGuiDemoSetting)
|
||||
const [version, setVersion] = useState<string>("")
|
||||
const [edition, setEdition] = useState<string>("")
|
||||
const getAppGuiSetting = async (url: string) => {
|
||||
const res = await fetch(`${url}`, {
|
||||
method: "GET",
|
||||
})
|
||||
const appSetting = await res.json() as AppGuiSetting
|
||||
setAppGuiSetting(appSetting)
|
||||
setGuiSettingLoaded(true)
|
||||
}
|
||||
const clearAppGuiSetting = () => {
|
||||
setAppGuiSetting(InitialAppGuiDemoSetting)
|
||||
setGuiSettingLoaded(false)
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const getVersionInfo = async () => {
|
||||
const res = await fetch(`/assets/gui_settings/version.txt`, {
|
||||
method: "GET",
|
||||
})
|
||||
const version = await res.text()
|
||||
setVersion(version)
|
||||
}
|
||||
getVersionInfo()
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
const getVersionInfo = async () => {
|
||||
const res = await fetch(`/assets/gui_settings/edition.txt`, {
|
||||
method: "GET",
|
||||
})
|
||||
const edition = await res.text()
|
||||
setEdition(edition)
|
||||
}
|
||||
getVersionInfo()
|
||||
}, [])
|
||||
|
||||
return {
|
||||
appGuiSetting,
|
||||
guiSettingLoaded,
|
||||
version,
|
||||
edition,
|
||||
getAppGuiSetting,
|
||||
clearAppGuiSetting,
|
||||
}
|
||||
}
|
||||
|
45
client/demo/src/001_globalHooks/001_useAudioConfig.ts
Normal file
@ -0,0 +1,45 @@
|
||||
import { useEffect, useState } from "react"
|
||||
|
||||
export type AudioConfigState = {
|
||||
audioContext: AudioContext | null
|
||||
}
|
||||
export const useAudioConfig = (): AudioConfigState => {
|
||||
const [audioContext, setAudioContext] = useState<AudioContext | null>(null)
|
||||
|
||||
useEffect(() => {
|
||||
const createAudioContext = () => {
|
||||
|
||||
const url = new URL(window.location.href);
|
||||
const params = url.searchParams;
|
||||
const sampleRate = params.get('sample_rate') || null
|
||||
let ctx: AudioContext
|
||||
if(sampleRate){
|
||||
if(sampleRate == "default"){
|
||||
console.log(`Sample rate: default`)
|
||||
ctx = new AudioContext()
|
||||
}else{
|
||||
console.log(`Sample rate: ${sampleRate}`)
|
||||
ctx = new AudioContext({ sampleRate: Number(sampleRate)})
|
||||
}
|
||||
}else{
|
||||
console.log(`Sample rate: default(48000)`)
|
||||
ctx = new AudioContext({ sampleRate: 48000})
|
||||
}
|
||||
|
||||
console.log(ctx)
|
||||
setAudioContext(ctx)
|
||||
|
||||
document.removeEventListener('touchstart', createAudioContext);
|
||||
document.removeEventListener('mousedown', createAudioContext);
|
||||
}
|
||||
document.addEventListener('touchstart', createAudioContext, false);
|
||||
document.addEventListener('mousedown', createAudioContext, false);
|
||||
}, [])
|
||||
|
||||
const ret: AudioConfigState = {
|
||||
audioContext
|
||||
}
|
||||
|
||||
return ret
|
||||
|
||||
}
|
23
client/demo/src/001_globalHooks/001_useVCClient.ts
Normal file
@ -0,0 +1,23 @@
|
||||
import { ClientState, useClient } from "@dannadori/voice-changer-client-js"
|
||||
|
||||
export type UseVCClientProps = {
|
||||
audioContext: AudioContext | null
|
||||
}
|
||||
|
||||
export type VCClientState = {
|
||||
clientState: ClientState
|
||||
}
|
||||
|
||||
export const useVCClient = (props: UseVCClientProps): VCClientState => {
|
||||
const clientState = useClient({
|
||||
audioContext: props.audioContext
|
||||
})
|
||||
|
||||
const ret: VCClientState = {
|
||||
clientState
|
||||
}
|
||||
|
||||
|
||||
return ret
|
||||
|
||||
}
|
37
client/demo/src/001_globalHooks/010_useMessageBuilder.ts
Normal file
@ -0,0 +1,37 @@
|
||||
import { useRef } from "react"
|
||||
|
||||
export type Message = {
|
||||
file: string,
|
||||
id: string,
|
||||
message: { [lang: string]: string }
|
||||
}
|
||||
|
||||
export type MessageBuilderStateAndMethod = {
|
||||
setMessage: (file: string, id: string, message: { [lang: string]: string }) => void
|
||||
getMessage: (file: string, id: string) => string
|
||||
}
|
||||
|
||||
export const useMessageBuilder_old = (): MessageBuilderStateAndMethod => {
|
||||
const messagesRef = useRef<Message[]>([])
|
||||
|
||||
const setMessage = (file: string, id: string, message: { [lang: string]: string }) => {
|
||||
if (messagesRef.current.find(x => { return x.file == file && x.id == id })) {
|
||||
console.warn("duplicate message is registerd", file, id, message)
|
||||
} else {
|
||||
messagesRef.current.push({ file, id, message })
|
||||
}
|
||||
}
|
||||
const getMessage = (file: string, id: string) => {
|
||||
let lang = window.navigator.language
|
||||
if (lang != "ja") {
|
||||
lang = "en"
|
||||
}
|
||||
|
||||
console.log(messagesRef.current)
|
||||
return messagesRef.current.find(x => { return x.file == file && x.id == id })?.message[lang] || "unknwon message"
|
||||
}
|
||||
return {
|
||||
setMessage,
|
||||
getMessage
|
||||
}
|
||||
}
|
299
client/demo/src/001_globalHooks/100_useWebInfo.ts
Normal file
@ -0,0 +1,299 @@
|
||||
import { ClientState, WebModelSlot } from "@dannadori/voice-changer-client-js";
|
||||
import { VoiceChangerJSClientConfig, VoiceChangerJSClient, ProgressUpdateType, ProgreeeUpdateCallbcckInfo, VoiceChangerType, InputLengthKey, ResponseTimeInfo } from "@dannadori/voice-changer-js";
|
||||
import { useEffect, useMemo, useRef, useState } from "react";
|
||||
|
||||
export type UseWebInfoProps = {
|
||||
clientState: ClientState | null;
|
||||
webEdition: boolean;
|
||||
};
|
||||
|
||||
export const WebModelLoadingState = {
|
||||
none: "none",
|
||||
loading: "loading",
|
||||
warmup: "warmup",
|
||||
ready: "ready",
|
||||
} as const;
|
||||
export type WebModelLoadingState = (typeof WebModelLoadingState)[keyof typeof WebModelLoadingState];
|
||||
|
||||
export type VoiceChangerConfig = {
|
||||
config: VoiceChangerJSClientConfig;
|
||||
modelUrl: string;
|
||||
portrait: string;
|
||||
name: string;
|
||||
termOfUse: string;
|
||||
sampleRate: ModelSampleRateStr;
|
||||
useF0: boolean;
|
||||
inputLength: InputLengthKey;
|
||||
progressCallback?: ((data: any) => void) | null;
|
||||
};
|
||||
export type WebInfoState = {
|
||||
voiceChangerConfig: VoiceChangerConfig;
|
||||
webModelLoadingState: WebModelLoadingState;
|
||||
progressLoadPreprocess: number;
|
||||
progressLoadVCModel: number;
|
||||
progressWarmup: number;
|
||||
webModelslot: WebModelSlot;
|
||||
upkey: number;
|
||||
responseTimeInfo: ResponseTimeInfo;
|
||||
};
|
||||
export type WebInfoStateAndMethod = WebInfoState & {
|
||||
loadVoiceChanagerModel: () => Promise<void>;
|
||||
setUpkey: (upkey: number) => void;
|
||||
setVoiceChangerConfig: (voiceChangerType: VoiceChangerType, sampleRate: ModelSampleRateStr, useF0: boolean, inputLength: InputLengthKey) => void;
|
||||
};
|
||||
|
||||
const ModelSampleRateStr = {
|
||||
"40k": "40k",
|
||||
"32k": "32k",
|
||||
"16k": "16k",
|
||||
} as const;
|
||||
type ModelSampleRateStr = (typeof ModelSampleRateStr)[keyof typeof ModelSampleRateStr];
|
||||
|
||||
const noF0ModelUrl: { [modelType in VoiceChangerType]: { [inputLength in InputLengthKey]: { [sampleRate in ModelSampleRateStr]: string } } } = {
|
||||
rvcv1: {
|
||||
"24000": {
|
||||
"40k": "https://huggingface.co/wok000/vcclient_model/resolve/main/web_model/v_01_alpha/amitaro/rvcv1_amitaro_v1_40k_nof0_24000.bin",
|
||||
"32k": "https://huggingface.co/wok000/vcclient_model/resolve/main/web_model/v_01_alpha/amitaro/rvcv1_amitaro_v1_32k_nof0_24000.bin",
|
||||
},
|
||||
"16000": {
|
||||
"40k": "https://huggingface.co/wok000/vcclient_model/resolve/main/web_model/v_01_alpha/amitaro/rvcv1_amitaro_v1_40k_nof0_16000.bin",
|
||||
"32k": "https://huggingface.co/wok000/vcclient_model/resolve/main/web_model/v_01_alpha/amitaro/rvcv1_amitaro_v1_32k_nof0_16000.bin",
|
||||
},
|
||||
"12000": {
|
||||
"40k": "https://huggingface.co/wok000/vcclient_model/resolve/main/web_model/v_01_alpha/amitaro/rvcv1_amitaro_v1_40k_nof0_12000.bin",
|
||||
"32k": "https://huggingface.co/wok000/vcclient_model/resolve/main/web_model/v_01_alpha/amitaro/rvcv1_amitaro_v1_32k_nof0_12000.bin",
|
||||
},
|
||||
"8000": {
|
||||
"40k": "https://huggingface.co/wok000/vcclient_model/resolve/main/web_model/v_01_alpha/amitaro/rvcv1_amitaro_v1_40k_nof0_8000.bin",
|
||||
"32k": "https://huggingface.co/wok000/vcclient_model/resolve/main/web_model/v_01_alpha/amitaro/rvcv1_amitaro_v1_32k_nof0_8000.bin",
|
||||
},
|
||||
},
|
||||
rvcv2: {
|
||||
"24000": {
|
||||
"40k": "https://huggingface.co/wok000/vcclient_model/resolve/main/web_model/v_01_alpha/amitaro/rvcv2_amitaro_v2_40k_nof0_24000.bin",
|
||||
"32k": "https://huggingface.co/wok000/vcclient_model/resolve/main/web_model/v_01_alpha/amitaro/rvcv2_amitaro_v2_32k_nof0_24000.bin",
|
||||
"16k": "https://huggingface.co/wok000/vcclient_model/resolve/main/web_model/v_01_alpha/amitaro/rvcv2_amitaro_v2_16k_nof0_24000.bin",
|
||||
},
|
||||
"16000": {
|
||||
"40k": "https://huggingface.co/wok000/vcclient_model/resolve/main/web_model/v_01_alpha/amitaro/rvcv2_amitaro_v2_40k_nof0_16000.bin",
|
||||
"32k": "https://huggingface.co/wok000/vcclient_model/resolve/main/web_model/v_01_alpha/amitaro/rvcv2_amitaro_v2_32k_nof0_16000.bin",
|
||||
"16k": "https://huggingface.co/wok000/vcclient_model/resolve/main/web_model/v_01_alpha/amitaro/rvcv2_amitaro_v2_16k_nof0_16000.bin",
|
||||
},
|
||||
"12000": {
|
||||
"40k": "https://huggingface.co/wok000/vcclient_model/resolve/main/web_model/v_01_alpha/amitaro/rvcv2_amitaro_v2_40k_nof0_12000.bin",
|
||||
"32k": "https://huggingface.co/wok000/vcclient_model/resolve/main/web_model/v_01_alpha/amitaro/rvcv2_amitaro_v2_32k_nof0_12000.bin",
|
||||
"16k": "https://huggingface.co/wok000/vcclient_model/resolve/main/web_model/v_01_alpha/amitaro/rvcv2_amitaro_v2_16k_nof0_12000.bin",
|
||||
},
|
||||
"8000": {
|
||||
"40k": "https://huggingface.co/wok000/vcclient_model/resolve/main/web_model/v_01_alpha/amitaro/rvcv2_amitaro_v2_40k_nof0_8000.bin",
|
||||
"32k": "https://huggingface.co/wok000/vcclient_model/resolve/main/web_model/v_01_alpha/amitaro/rvcv2_amitaro_v2_32k_nof0_8000.bin",
|
||||
"16k": "https://huggingface.co/wok000/vcclient_model/resolve/main/web_model/v_01_alpha/amitaro/rvcv2_amitaro_v2_16k_nof0_8000.bin",
|
||||
},
|
||||
},
|
||||
};
|
||||
const f0ModelUrl: { [modelType in VoiceChangerType]: { [inputLength in InputLengthKey]: { [sampleRate in ModelSampleRateStr]: string } } } = {
|
||||
rvcv1: {
|
||||
"24000": {
|
||||
"40k": "https://huggingface.co/wok000/vcclient_model/resolve/main/web_model/v_01_alpha/amitaro/rvcv1_amitaro_v1_40k_f0_24000.bin",
|
||||
"32k": "https://huggingface.co/wok000/vcclient_model/resolve/main/web_model/v_01_alpha/amitaro/rvcv1_amitaro_v1_32k_f0_24000.bin",
|
||||
},
|
||||
"16000": {
|
||||
"40k": "https://huggingface.co/wok000/vcclient_model/resolve/main/web_model/v_01_alpha/amitaro/rvcv1_amitaro_v1_40k_f0_16000.bin",
|
||||
"32k": "https://huggingface.co/wok000/vcclient_model/resolve/main/web_model/v_01_alpha/amitaro/rvcv1_amitaro_v1_32k_f0_16000.bin",
|
||||
},
|
||||
"12000": {
|
||||
"40k": "https://huggingface.co/wok000/vcclient_model/resolve/main/web_model/v_01_alpha/amitaro/rvcv1_amitaro_v1_40k_f0_12000.bin",
|
||||
"32k": "https://huggingface.co/wok000/vcclient_model/resolve/main/web_model/v_01_alpha/amitaro/rvcv1_amitaro_v1_32k_f0_12000.bin",
|
||||
},
|
||||
"8000": {
|
||||
"40k": "https://huggingface.co/wok000/vcclient_model/resolve/main/web_model/v_01_alpha/amitaro/rvcv1_amitaro_v1_40k_f0_8000.bin",
|
||||
"32k": "https://huggingface.co/wok000/vcclient_model/resolve/main/web_model/v_01_alpha/amitaro/rvcv1_amitaro_v1_32k_f0_8000.bin",
|
||||
},
|
||||
},
|
||||
rvcv2: {
|
||||
"24000": {
|
||||
"40k": "https://huggingface.co/wok000/vcclient_model/resolve/main/web_model/v_01_alpha/amitaro/rvcv2_amitaro_v2_40k_f0_24000.bin",
|
||||
// "32k": "https://huggingface.co/wok000/vcclient_model/resolve/main/web_model/v_01_alpha/amitaro/rvcv2_amitaro_v2_32k_f0_24000.bin",
|
||||
"32k": "https://192.168.0.247:8080/models/rvcv2_exp_v2_32k_f0_24000.bin",
|
||||
// "16k": "https://huggingface.co/wok000/vcclient_model/resolve/main/web_model/v_01_alpha/amitaro/rvcv2_amitaro_v2_16k_f0_24000.bin",
|
||||
// "16k": "https://huggingface.co/wok000/vcclient_model/resolve/main/web_model/v_01_alpha/vctk/rvcv2_vctk_v2_16k_f0_24000.bin",
|
||||
"16k": "https://192.168.0.247:8080/models/rvcv2_vctk_v2_16k_f0_24000.bin",
|
||||
},
|
||||
"16000": {
|
||||
"40k": "https://huggingface.co/wok000/vcclient_model/resolve/main/web_model/v_01_alpha/amitaro/rvcv2_amitaro_v2_40k_f0_16000.bin",
|
||||
"32k": "https://huggingface.co/wok000/vcclient_model/resolve/main/web_model/v_01_alpha/amitaro/rvcv2_amitaro_v2_32k_f0_16000.bin",
|
||||
// "16k": "https://huggingface.co/wok000/vcclient_model/resolve/main/web_model/v_01_alpha/amitaro/rvcv2_amitaro_v2_16k_f0_16000.bin",
|
||||
"16k": "https://huggingface.co/wok000/vcclient_model/resolve/main/web_model/v_01_alpha/vctk/rvcv2_vctk_v2_16k_f0_16000.bin",
|
||||
},
|
||||
"12000": {
|
||||
"40k": "https://huggingface.co/wok000/vcclient_model/resolve/main/web_model/v_01_alpha/amitaro/rvcv2_amitaro_v2_40k_f0_12000.bin",
|
||||
"32k": "https://huggingface.co/wok000/vcclient_model/resolve/main/web_model/v_01_alpha/amitaro/rvcv2_amitaro_v2_32k_f0_12000.bin",
|
||||
// "16k": "https://huggingface.co/wok000/vcclient_model/resolve/main/web_model/v_01_alpha/amitaro/rvcv2_amitaro_v2_16k_f0_12000.bin",
|
||||
"16k": "https://huggingface.co/wok000/vcclient_model/resolve/main/web_model/v_01_alpha/vctk/rvcv2_vctk_v2_16k_f0_16000.bin",
|
||||
},
|
||||
"8000": {
|
||||
"40k": "https://huggingface.co/wok000/vcclient_model/resolve/main/web_model/v_01_alpha/amitaro/rvcv2_amitaro_v2_40k_f0_8000.bin",
|
||||
"32k": "https://huggingface.co/wok000/vcclient_model/resolve/main/web_model/v_01_alpha/amitaro/rvcv2_amitaro_v2_32k_f0_8000.bin",
|
||||
// "16k": "https://huggingface.co/wok000/vcclient_model/resolve/main/web_model/v_01_alpha/amitaro/rvcv2_amitaro_v2_16k_f0_8000.bin",
|
||||
"16k": "https://huggingface.co/wok000/vcclient_model/resolve/main/web_model/v_01_alpha/vctk/rvcv2_vctk_v2_16k_f0_8000.bin",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const useWebInfo = (props: UseWebInfoProps): WebInfoStateAndMethod => {
|
||||
const initVoiceChangerType: VoiceChangerType = "rvcv2";
|
||||
const initInputLength: InputLengthKey = "24000";
|
||||
const initUseF0 = true;
|
||||
const initSampleRate: ModelSampleRateStr = "32k";
|
||||
|
||||
const progressCallback = (data: ProgreeeUpdateCallbcckInfo) => {
|
||||
if (data.progressUpdateType === ProgressUpdateType.loadPreprocessModel) {
|
||||
setProgressLoadPreprocess(data.progress);
|
||||
} else if (data.progressUpdateType === ProgressUpdateType.loadVCModel) {
|
||||
setProgressLoadVCModel(data.progress);
|
||||
} else if (data.progressUpdateType === ProgressUpdateType.checkResponseTime) {
|
||||
setProgressWarmup(data.progress);
|
||||
}
|
||||
};
|
||||
|
||||
const generateVoiceChangerConfig = (voiceChangerType: VoiceChangerType, sampleRate: ModelSampleRateStr, useF0: boolean, inputLength: InputLengthKey) => {
|
||||
let modelUrl;
|
||||
if (useF0) {
|
||||
modelUrl = f0ModelUrl[voiceChangerType][inputLength][sampleRate];
|
||||
} else {
|
||||
modelUrl = noF0ModelUrl[voiceChangerType][inputLength][sampleRate];
|
||||
}
|
||||
|
||||
const config: VoiceChangerConfig = {
|
||||
config: {
|
||||
voiceChangerType: voiceChangerType,
|
||||
inputLength: inputLength,
|
||||
baseUrl: window.location.origin,
|
||||
inputSamplingRate: 48000,
|
||||
outputSamplingRate: 48000,
|
||||
},
|
||||
modelUrl: modelUrl,
|
||||
portrait: "https://huggingface.co/wok000/vcclient_model/resolve/main/web_model/v_01_alpha/amitaro/amitaro.png",
|
||||
name: "あみたろ",
|
||||
termOfUse: "https://huggingface.co/wok000/vcclient_model/raw/main/rvc/amitaro_contentvec_256/term_of_use.txt",
|
||||
sampleRate: sampleRate,
|
||||
useF0: useF0,
|
||||
inputLength: inputLength,
|
||||
progressCallback,
|
||||
};
|
||||
return config;
|
||||
};
|
||||
|
||||
const [voiceChangerConfig, _setVoiceChangerConfig] = useState<VoiceChangerConfig>(generateVoiceChangerConfig(initVoiceChangerType, initSampleRate, initUseF0, initInputLength));
|
||||
const [webModelLoadingState, setWebModelLoadingState] = useState<WebModelLoadingState>(WebModelLoadingState.none);
|
||||
const [progressLoadPreprocess, setProgressLoadPreprocess] = useState<number>(0);
|
||||
const [progressLoadVCModel, setProgressLoadVCModel] = useState<number>(0);
|
||||
const [progressWarmup, setProgressWarmup] = useState<number>(0);
|
||||
const [upkey, setUpkey] = useState<number>(0);
|
||||
const [responseTimeInfo, setResponseTimeInfo] = useState<ResponseTimeInfo>({
|
||||
responseTime: 0,
|
||||
realDuration: 0,
|
||||
rtf: 0,
|
||||
});
|
||||
const voiceChangerJSClient = useRef<VoiceChangerJSClient>();
|
||||
|
||||
const webModelslot: WebModelSlot = useMemo(() => {
|
||||
return {
|
||||
slotIndex: -1,
|
||||
voiceChangerType: "WebModel",
|
||||
name: voiceChangerConfig.name,
|
||||
description: "",
|
||||
credit: "",
|
||||
termsOfUseUrl: voiceChangerConfig.termOfUse,
|
||||
iconFile: voiceChangerConfig.portrait,
|
||||
speakers: {},
|
||||
defaultTune: 0,
|
||||
modelType: "pyTorchRVCNono",
|
||||
f0: voiceChangerConfig.useF0,
|
||||
samplingRate: 0,
|
||||
modelFile: "",
|
||||
};
|
||||
}, []);
|
||||
|
||||
const setVoiceChangerConfig = (voiceChangerType: VoiceChangerType, sampleRate: ModelSampleRateStr, useF0: boolean, inputLength: InputLengthKey) => {
|
||||
const config = generateVoiceChangerConfig(voiceChangerType, sampleRate, useF0, inputLength);
|
||||
_setVoiceChangerConfig(config);
|
||||
};
|
||||
// useEffect(() => {
|
||||
// setVoiceChangerConfig({ ...voiceChangerConfig, progressCallback });
|
||||
// }, []);
|
||||
|
||||
const loadVoiceChanagerModel = async () => {
|
||||
if (!props.clientState) {
|
||||
throw new Error("[useWebInfo] clientState is null");
|
||||
}
|
||||
if (!props.clientState.initialized) {
|
||||
console.warn("[useWebInfo] clientState is not initialized yet");
|
||||
return;
|
||||
}
|
||||
if (!props.webEdition) {
|
||||
console.warn("[useWebInfo] this is not web edition");
|
||||
return;
|
||||
}
|
||||
console.log("loadVoiceChanagerModel1", voiceChangerConfig);
|
||||
setWebModelLoadingState("loading");
|
||||
voiceChangerJSClient.current = new VoiceChangerJSClient();
|
||||
await voiceChangerJSClient.current.initialize(voiceChangerConfig.config, voiceChangerConfig.modelUrl, voiceChangerConfig.progressCallback);
|
||||
console.log("loadVoiceChanagerModel2");
|
||||
|
||||
// worm up
|
||||
setWebModelLoadingState("warmup");
|
||||
const warmupResult = await voiceChangerJSClient.current.checkResponseTime();
|
||||
console.log("warmup result", warmupResult);
|
||||
|
||||
// check time
|
||||
const responseTimeInfo = await voiceChangerJSClient.current.checkResponseTime();
|
||||
console.log("responseTimeInfo", responseTimeInfo);
|
||||
setResponseTimeInfo(responseTimeInfo);
|
||||
|
||||
props.clientState?.setInternalAudioProcessCallback({
|
||||
processAudio: async (data: Uint8Array) => {
|
||||
const audioF32 = new Float32Array(data.buffer);
|
||||
const res = await voiceChangerJSClient.current!.convert(audioF32);
|
||||
const audio = new Uint8Array(res[0].buffer);
|
||||
if (res[1]) {
|
||||
console.log("RESPONSE!", res[1]);
|
||||
setResponseTimeInfo(res[1]);
|
||||
}
|
||||
return audio;
|
||||
},
|
||||
});
|
||||
setWebModelLoadingState("ready");
|
||||
};
|
||||
useEffect(() => {
|
||||
if (!voiceChangerJSClient.current) {
|
||||
console.log("setupkey", voiceChangerJSClient.current);
|
||||
return;
|
||||
}
|
||||
voiceChangerJSClient.current.setUpkey(upkey);
|
||||
}, [upkey]);
|
||||
|
||||
useEffect(() => {
|
||||
console.log("change voice ", voiceChangerConfig);
|
||||
|
||||
setProgressLoadPreprocess(0);
|
||||
setProgressLoadVCModel(0);
|
||||
setProgressWarmup(0);
|
||||
|
||||
loadVoiceChanagerModel();
|
||||
}, [voiceChangerConfig, props.clientState?.initialized]);
|
||||
|
||||
return {
|
||||
voiceChangerConfig,
|
||||
webModelLoadingState,
|
||||
progressLoadPreprocess,
|
||||
progressLoadVCModel,
|
||||
progressWarmup,
|
||||
webModelslot,
|
||||
upkey,
|
||||
responseTimeInfo,
|
||||
loadVoiceChanagerModel,
|
||||
setUpkey,
|
||||
setVoiceChangerConfig,
|
||||
};
|
||||
};
|
38
client/demo/src/001_provider/001_AppRootProvider.tsx
Normal file
@ -0,0 +1,38 @@
|
||||
import React, { useContext } from "react";
|
||||
import { ReactNode } from "react";
|
||||
import { AppGuiSettingStateAndMethod, useAppGuiSetting } from "../001_globalHooks/001_useAppGuiSetting";
|
||||
import { AudioConfigState, useAudioConfig } from "../001_globalHooks/001_useAudioConfig";
|
||||
|
||||
type Props = {
|
||||
children: ReactNode;
|
||||
};
|
||||
|
||||
type AppRootValue = {
|
||||
audioContextState: AudioConfigState;
|
||||
appGuiSettingState: AppGuiSettingStateAndMethod;
|
||||
getGUISetting: () => Promise<void>;
|
||||
};
|
||||
|
||||
const AppRootContext = React.createContext<AppRootValue | null>(null);
|
||||
export const useAppRoot = (): AppRootValue => {
|
||||
const state = useContext(AppRootContext);
|
||||
if (!state) {
|
||||
throw new Error("useAppState must be used within AppStateProvider");
|
||||
}
|
||||
return state;
|
||||
};
|
||||
|
||||
export const AppRootProvider = ({ children }: Props) => {
|
||||
const audioContextState = useAudioConfig();
|
||||
const appGuiSettingState = useAppGuiSetting();
|
||||
|
||||
const getGUISetting = async () => {
|
||||
await appGuiSettingState.getAppGuiSetting(`/assets/gui_settings/GUI.json`);
|
||||
};
|
||||
const providerValue: AppRootValue = {
|
||||
audioContextState,
|
||||
appGuiSettingState,
|
||||
getGUISetting,
|
||||
};
|
||||
return <AppRootContext.Provider value={providerValue}>{children}</AppRootContext.Provider>;
|
||||
};
|
79
client/demo/src/001_provider/001_AppStateProvider.tsx
Normal file
@ -0,0 +1,79 @@
|
||||
import { ClientState } from "@dannadori/voice-changer-client-js";
|
||||
import { VoiceChangerJSClient } from "@dannadori/voice-changer-js";
|
||||
import React, { useContext, useEffect, useRef } from "react";
|
||||
import { ReactNode } from "react";
|
||||
import { useVCClient } from "../001_globalHooks/001_useVCClient";
|
||||
import { useAppRoot } from "./001_AppRootProvider";
|
||||
import { useMessageBuilder } from "../hooks/useMessageBuilder";
|
||||
import { WebInfoStateAndMethod, useWebInfo } from "../001_globalHooks/100_useWebInfo";
|
||||
|
||||
type Props = {
|
||||
children: ReactNode;
|
||||
};
|
||||
|
||||
type AppStateValue = ClientState & {
|
||||
audioContext: AudioContext;
|
||||
initializedRef: React.MutableRefObject<boolean>;
|
||||
webInfoState: WebInfoStateAndMethod;
|
||||
webEdition: boolean;
|
||||
};
|
||||
|
||||
const AppStateContext = React.createContext<AppStateValue | null>(null);
|
||||
export const useAppState = (): AppStateValue => {
|
||||
const state = useContext(AppStateContext);
|
||||
if (!state) {
|
||||
throw new Error("useAppState must be used within AppStateProvider");
|
||||
}
|
||||
return state;
|
||||
};
|
||||
|
||||
export const AppStateProvider = ({ children }: Props) => {
|
||||
const appRoot = useAppRoot();
|
||||
const webEdition = appRoot.appGuiSettingState.edition.indexOf("web") >= 0;
|
||||
const clientState = useVCClient({ audioContext: appRoot.audioContextState.audioContext });
|
||||
const messageBuilderState = useMessageBuilder();
|
||||
const webInfoState = useWebInfo({ clientState: clientState.clientState, webEdition: webEdition });
|
||||
// const voiceChangerJSClient = useRef<VoiceChangerJSClient>();
|
||||
|
||||
useEffect(() => {
|
||||
messageBuilderState.setMessage(__filename, "ioError", {
|
||||
ja: "エラーが頻発しています。対象としているフレームワークのモデルがロードされているか確認してください。",
|
||||
en: "Frequent errors occur. Please check if the model of the framework being targeted is loaded.",
|
||||
});
|
||||
}, []);
|
||||
|
||||
const initializedRef = useRef<boolean>(false);
|
||||
useEffect(() => {
|
||||
if (clientState.clientState.initialized) {
|
||||
initializedRef.current = true;
|
||||
clientState.clientState.getInfo();
|
||||
// clientState.clientState.setVoiceChangerClientSetting({
|
||||
// ...clientState.clientState.setting.voiceChangerClientSetting
|
||||
// })
|
||||
}
|
||||
}, [clientState.clientState.initialized]);
|
||||
|
||||
useEffect(() => {
|
||||
if (clientState.clientState.ioErrorCount > 100) {
|
||||
alert(messageBuilderState.getMessage(__filename, "ioError"));
|
||||
clientState.clientState.resetIoErrorCount();
|
||||
}
|
||||
}, [clientState.clientState.ioErrorCount]);
|
||||
|
||||
useEffect(() => {
|
||||
if (appRoot.appGuiSettingState.edition.indexOf("web") >= 0 && clientState.clientState.initialized) {
|
||||
clientState.clientState.setWorkletNodeSetting({ ...clientState.clientState.setting.workletNodeSetting, protocol: "internal" });
|
||||
// webInfoState.loadVoiceChanagerModel(); // hook内でuseEffectでinvoke
|
||||
}
|
||||
}, [clientState.clientState.initialized]);
|
||||
|
||||
const providerValue: AppStateValue = {
|
||||
audioContext: appRoot.audioContextState.audioContext!,
|
||||
...clientState.clientState,
|
||||
initializedRef,
|
||||
webInfoState,
|
||||
webEdition,
|
||||
};
|
||||
|
||||
return <AppStateContext.Provider value={providerValue}>{children}</AppStateContext.Provider>;
|
||||
};
|
63
client/demo/src/001_provider/900_ErrorBoundary.tsx
Normal file
@ -0,0 +1,63 @@
|
||||
import React, { ErrorInfo } from "react";
|
||||
|
||||
type ErrorBoundaryProps = {
|
||||
children: React.ReactNode;
|
||||
fallback: React.ReactNode;
|
||||
onError: (error: Error, errorInfo: React.ErrorInfo | null, reason: any) => void;
|
||||
};
|
||||
|
||||
type ErrorBoundaryState = {
|
||||
hasError: boolean;
|
||||
};
|
||||
|
||||
class ErrorBoundary extends React.Component<ErrorBoundaryProps, ErrorBoundaryState> {
|
||||
// @ts-ignore
|
||||
private eventHandler: () => void;
|
||||
constructor(props: ErrorBoundaryProps) {
|
||||
super(props);
|
||||
this.state = { hasError: false };
|
||||
this.eventHandler = this.updateError.bind(this);
|
||||
}
|
||||
|
||||
static getDerivedStateFromError(_error: Error) {
|
||||
// console.warn("React Error Boundary Catch", error)
|
||||
return { hasError: true };
|
||||
}
|
||||
componentDidCatch(error: Error, errorInfo: ErrorInfo) {
|
||||
// For logging
|
||||
console.warn("React Error Boundary Catch", error, errorInfo);
|
||||
const { onError } = this.props;
|
||||
if (onError) {
|
||||
onError(error, errorInfo, null);
|
||||
}
|
||||
}
|
||||
|
||||
// 非同期例外対応
|
||||
updateError() {
|
||||
this.setState({ hasError: true });
|
||||
}
|
||||
handledRejection = (event: PromiseRejectionEvent) => {
|
||||
const { onError } = this.props;
|
||||
const error = new Error(event.type);
|
||||
onError(error, null, event.reason);
|
||||
this.setState({ hasError: true });
|
||||
};
|
||||
componentDidMount() {
|
||||
// window.addEventListener('unhandledrejection', this.eventHandler)
|
||||
window.addEventListener("unhandledrejection", this.handledRejection);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
// window.removeEventListener('unhandledrejection', this.eventHandler)
|
||||
window.removeEventListener("unhandledrejection", this.handledRejection);
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.state.hasError) {
|
||||
return this.props.fallback;
|
||||
}
|
||||
return this.props.children;
|
||||
}
|
||||
}
|
||||
|
||||
export default ErrorBoundary;
|
41
client/demo/src/001_provider/_BlockingQueue.ts
Normal file
@ -0,0 +1,41 @@
|
||||
export class BlockingQueue<T> {
|
||||
private _promises: Promise<T>[];
|
||||
private _resolvers: ((t: T) => void)[];
|
||||
|
||||
constructor() {
|
||||
this._resolvers = [];
|
||||
this._promises = [];
|
||||
}
|
||||
|
||||
private _add() {
|
||||
this._promises.push(
|
||||
new Promise((resolve) => {
|
||||
this._resolvers.push(resolve);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
enqueue(t: T) {
|
||||
if (this._resolvers.length == 0) this._add();
|
||||
const resolve = this._resolvers.shift()!;
|
||||
resolve(t);
|
||||
}
|
||||
|
||||
dequeue() {
|
||||
if (this._promises.length == 0) this._add();
|
||||
const promise = this._promises.shift()!;
|
||||
return promise;
|
||||
}
|
||||
|
||||
isEmpty() {
|
||||
return this._promises.length == 0;
|
||||
}
|
||||
|
||||
isBlocked() {
|
||||
return this._resolvers.length != 0;
|
||||
}
|
||||
|
||||
get length() {
|
||||
return this._promises.length - this._resolvers.length;
|
||||
}
|
||||
}
|
@ -1,69 +0,0 @@
|
||||
import * as React from "react";
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { AUDIO_ELEMENT_FOR_PLAY_RESULT } from "./const";
|
||||
import { useServerSettingArea } from "./101_server_setting";
|
||||
import { useDeviceSetting } from "./102_device_setting";
|
||||
import { useConvertSetting } from "./104_convert_setting";
|
||||
import { useAdvancedSetting } from "./105_advanced_setting";
|
||||
import { useSpeakerSetting } from "./103_speaker_setting";
|
||||
import { useServerControl } from "./106_server_control";
|
||||
import { useClient } from "@dannadori/voice-changer-client-js";
|
||||
|
||||
export const useMicrophoneOptions = () => {
|
||||
const [audioContext, setAudioContext] = useState<AudioContext | null>(null)
|
||||
|
||||
const clientState = useClient({
|
||||
audioContext: audioContext,
|
||||
audioOutputElementId: AUDIO_ELEMENT_FOR_PLAY_RESULT
|
||||
})
|
||||
|
||||
const serverSetting = useServerSettingArea({ clientState })
|
||||
const deviceSetting = useDeviceSetting(audioContext, { clientState })
|
||||
const speakerSetting = useSpeakerSetting({ clientState })
|
||||
const convertSetting = useConvertSetting({ clientState })
|
||||
const advancedSetting = useAdvancedSetting({ clientState })
|
||||
const serverControl = useServerControl({ clientState })
|
||||
|
||||
const clearSetting = async () => {
|
||||
await clientState.clearSetting()
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const createAudioContext = () => {
|
||||
const ctx = new AudioContext()
|
||||
setAudioContext(ctx)
|
||||
document.removeEventListener('touchstart', createAudioContext);
|
||||
document.removeEventListener('mousedown', createAudioContext);
|
||||
}
|
||||
document.addEventListener('touchstart', createAudioContext);
|
||||
document.addEventListener('mousedown', createAudioContext);
|
||||
}, [])
|
||||
|
||||
|
||||
const voiceChangerSetting = useMemo(() => {
|
||||
return (
|
||||
<>
|
||||
<div className="body-row left-padding-1">
|
||||
<div className="body-section-title">Virtual Microphone</div>
|
||||
</div>
|
||||
{serverControl.serverControl}
|
||||
{serverSetting.serverSetting}
|
||||
{deviceSetting.deviceSetting}
|
||||
{speakerSetting.speakerSetting}
|
||||
{convertSetting.convertSetting}
|
||||
{advancedSetting.advancedSetting}
|
||||
</>
|
||||
)
|
||||
}, [serverControl.serverControl,
|
||||
serverSetting.serverSetting,
|
||||
deviceSetting.deviceSetting,
|
||||
speakerSetting.speakerSetting,
|
||||
convertSetting.convertSetting,
|
||||
advancedSetting.advancedSetting])
|
||||
|
||||
return {
|
||||
voiceChangerSetting,
|
||||
clearSetting
|
||||
}
|
||||
}
|
||||
|
@ -1,226 +0,0 @@
|
||||
import { OnnxExecutionProvider, Framework, fileSelector } from "@dannadori/voice-changer-client-js"
|
||||
import React, { useState } from "react"
|
||||
import { useMemo } from "react"
|
||||
import { ClientState } from "@dannadori/voice-changer-client-js";
|
||||
|
||||
export type UseServerSettingProps = {
|
||||
clientState: ClientState
|
||||
}
|
||||
|
||||
export type ServerSettingState = {
|
||||
serverSetting: JSX.Element;
|
||||
}
|
||||
|
||||
export const useServerSettingArea = (props: UseServerSettingProps): ServerSettingState => {
|
||||
const [showPyTorch, setShowPyTorch] = useState<boolean>(false)
|
||||
const uploadeModelRow = useMemo(() => {
|
||||
const onPyTorchFileLoadClicked = async () => {
|
||||
const file = await fileSelector("")
|
||||
if (file.name.endsWith(".pth") == false) {
|
||||
alert("モデルファイルの拡張子はpthである必要があります。")
|
||||
return
|
||||
}
|
||||
props.clientState.serverSetting.setFileUploadSetting({
|
||||
...props.clientState.serverSetting.fileUploadSetting,
|
||||
pyTorchModel: {
|
||||
file: file
|
||||
}
|
||||
})
|
||||
}
|
||||
const onPyTorchFileClearClicked = () => {
|
||||
props.clientState.serverSetting.setFileUploadSetting({
|
||||
...props.clientState.serverSetting.fileUploadSetting,
|
||||
pyTorchModel: null
|
||||
})
|
||||
}
|
||||
const onConfigFileLoadClicked = async () => {
|
||||
const file = await fileSelector("")
|
||||
if (file.name.endsWith(".json") == false) {
|
||||
alert("モデルファイルの拡張子はjsonである必要があります。")
|
||||
return
|
||||
}
|
||||
props.clientState.serverSetting.setFileUploadSetting({
|
||||
...props.clientState.serverSetting.fileUploadSetting,
|
||||
configFile: {
|
||||
file: file
|
||||
}
|
||||
})
|
||||
}
|
||||
const onConfigFileClearClicked = () => {
|
||||
props.clientState.serverSetting.setFileUploadSetting({
|
||||
...props.clientState.serverSetting.fileUploadSetting,
|
||||
configFile: null
|
||||
})
|
||||
}
|
||||
const onOnnxFileLoadClicked = async () => {
|
||||
const file = await fileSelector("")
|
||||
if (file.name.endsWith(".onnx") == false) {
|
||||
alert("モデルファイルの拡張子はonnxである必要があります。")
|
||||
return
|
||||
}
|
||||
props.clientState.serverSetting.setFileUploadSetting({
|
||||
...props.clientState.serverSetting.fileUploadSetting,
|
||||
onnxModel: {
|
||||
file: file
|
||||
}
|
||||
})
|
||||
}
|
||||
const onOnnxFileClearClicked = () => {
|
||||
props.clientState.serverSetting.setFileUploadSetting({
|
||||
...props.clientState.serverSetting.fileUploadSetting,
|
||||
onnxModel: null
|
||||
})
|
||||
}
|
||||
const onModelUploadClicked = async () => {
|
||||
props.clientState.serverSetting.loadModel()
|
||||
}
|
||||
|
||||
const uploadButtonClassName = props.clientState.serverSetting.isUploading ? "body-button-disabled" : "body-button"
|
||||
const uploadButtonAction = props.clientState.serverSetting.isUploading ? () => { } : onModelUploadClicked
|
||||
const uploadButtonLabel = props.clientState.serverSetting.isUploading ? "wait..." : "upload"
|
||||
|
||||
const configFilenameText = props.clientState.serverSetting.fileUploadSetting.configFile?.filename || props.clientState.serverSetting.fileUploadSetting.configFile?.file?.name || ""
|
||||
const onnxModelFilenameText = props.clientState.serverSetting.fileUploadSetting.onnxModel?.filename || props.clientState.serverSetting.fileUploadSetting.onnxModel?.file?.name || ""
|
||||
const pyTorchFilenameText = props.clientState.serverSetting.fileUploadSetting.pyTorchModel?.filename || props.clientState.serverSetting.fileUploadSetting.pyTorchModel?.file?.name || ""
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="body-row split-3-3-4 left-padding-1 guided">
|
||||
<div className="body-item-title left-padding-1">Model Uploader</div>
|
||||
<div className="body-item-text">
|
||||
<div></div>
|
||||
</div>
|
||||
<div className="body-item-text">
|
||||
<div>
|
||||
<input type="checkbox" checked={showPyTorch} onChange={(e) => {
|
||||
setShowPyTorch(e.target.checked)
|
||||
}} /> enable PyTorch
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="body-row split-3-3-4 left-padding-1 guided">
|
||||
<div className="body-item-title left-padding-2">Config(.json)</div>
|
||||
<div className="body-item-text">
|
||||
<div>{configFilenameText}</div>
|
||||
</div>
|
||||
<div className="body-button-container">
|
||||
<div className="body-button" onClick={onConfigFileLoadClicked}>select</div>
|
||||
<div className="body-button left-margin-1" onClick={onConfigFileClearClicked}>clear</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="body-row split-3-3-4 left-padding-1 guided">
|
||||
<div className="body-item-title left-padding-2">Onnx(.onnx)</div>
|
||||
<div className="body-item-text">
|
||||
<div>{onnxModelFilenameText}</div>
|
||||
</div>
|
||||
<div className="body-button-container">
|
||||
<div className="body-button" onClick={onOnnxFileLoadClicked}>select</div>
|
||||
<div className="body-button left-margin-1" onClick={onOnnxFileClearClicked}>clear</div>
|
||||
</div>
|
||||
</div>
|
||||
{showPyTorch ?
|
||||
(
|
||||
<div className="body-row split-3-3-4 left-padding-1 guided">
|
||||
<div className="body-item-title left-padding-2">PyTorch(.pth)</div>
|
||||
<div className="body-item-text">
|
||||
<div>{pyTorchFilenameText}</div>
|
||||
</div>
|
||||
<div className="body-button-container">
|
||||
<div className="body-button" onClick={onPyTorchFileLoadClicked}>select</div>
|
||||
<div className="body-button left-margin-1" onClick={onPyTorchFileClearClicked}>clear</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
)
|
||||
:
|
||||
(
|
||||
<></>
|
||||
)
|
||||
}
|
||||
<div className="body-row split-3-3-4 left-padding-1 guided">
|
||||
<div className="body-item-title left-padding-2"></div>
|
||||
<div className="body-item-text">
|
||||
{props.clientState.serverSetting.isUploading ? `uploading.... ${props.clientState.serverSetting.uploadProgress}%` : ""}
|
||||
</div>
|
||||
<div className="body-button-container">
|
||||
<div className={uploadButtonClassName} onClick={uploadButtonAction}>{uploadButtonLabel}</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}, [
|
||||
props.clientState.serverSetting.fileUploadSetting,
|
||||
props.clientState.serverSetting.loadModel,
|
||||
props.clientState.serverSetting.isUploading,
|
||||
props.clientState.serverSetting.uploadProgress,
|
||||
showPyTorch])
|
||||
|
||||
const frameworkRow = useMemo(() => {
|
||||
const onFrameworkChanged = async (val: Framework) => {
|
||||
props.clientState.serverSetting.setFramework(val)
|
||||
}
|
||||
return (
|
||||
<div className="body-row split-3-7 left-padding-1 guided">
|
||||
<div className="body-item-title left-padding-1">Framework</div>
|
||||
<div className="body-select-container">
|
||||
<select className="body-select" value={props.clientState.serverSetting.setting.framework} onChange={(e) => {
|
||||
onFrameworkChanged(e.target.value as
|
||||
Framework)
|
||||
}}>
|
||||
{
|
||||
Object.values(Framework).map(x => {
|
||||
return <option key={x} value={x}>{x}</option>
|
||||
})
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}, [props.clientState.serverSetting.setting.framework, props.clientState.serverSetting.setFramework])
|
||||
|
||||
const onnxExecutionProviderRow = useMemo(() => {
|
||||
if (props.clientState.serverSetting.setting.framework != "ONNX") {
|
||||
return
|
||||
}
|
||||
const onOnnxExecutionProviderChanged = async (val: OnnxExecutionProvider) => {
|
||||
props.clientState.serverSetting.setOnnxExecutionProvider(val)
|
||||
}
|
||||
return (
|
||||
<div className="body-row split-3-7 left-padding-1">
|
||||
<div className="body-item-title left-padding-2">OnnxExecutionProvider</div>
|
||||
<div className="body-select-container">
|
||||
<select className="body-select" value={props.clientState.serverSetting.setting.onnxExecutionProvider} onChange={(e) => {
|
||||
onOnnxExecutionProviderChanged(e.target.value as
|
||||
OnnxExecutionProvider)
|
||||
}}>
|
||||
{
|
||||
Object.values(OnnxExecutionProvider).map(x => {
|
||||
return <option key={x} value={x}>{x}</option>
|
||||
})
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}, [props.clientState.serverSetting.setting.framework, props.clientState.serverSetting.setting.onnxExecutionProvider, props.clientState.serverSetting.setOnnxExecutionProvider])
|
||||
|
||||
const serverSetting = useMemo(() => {
|
||||
return (
|
||||
<>
|
||||
<div className="body-row split-3-7 left-padding-1">
|
||||
<div className="body-sub-section-title">Server Setting</div>
|
||||
<div className="body-select-container">
|
||||
</div>
|
||||
</div>
|
||||
{uploadeModelRow}
|
||||
{frameworkRow}
|
||||
{onnxExecutionProviderRow}
|
||||
</>
|
||||
)
|
||||
}, [uploadeModelRow, frameworkRow, onnxExecutionProviderRow])
|
||||
|
||||
|
||||
return {
|
||||
serverSetting,
|
||||
}
|
||||
}
|
@ -1,236 +0,0 @@
|
||||
import { fileSelectorAsDataURL, useIndexedDB } from "@dannadori/voice-changer-client-js"
|
||||
import React, { useEffect, useMemo, useState } from "react"
|
||||
import { AUDIO_ELEMENT_FOR_PLAY_RESULT, AUDIO_ELEMENT_FOR_TEST_CONVERTED, AUDIO_ELEMENT_FOR_TEST_CONVERTED_ECHOBACK, AUDIO_ELEMENT_FOR_TEST_ORIGINAL, INDEXEDDB_KEY_AUDIO_OUTPUT } from "./const"
|
||||
import { ClientState } from "@dannadori/voice-changer-client-js";
|
||||
|
||||
|
||||
const reloadDevices = async () => {
|
||||
try {
|
||||
const ms = await navigator.mediaDevices.getUserMedia({ video: false, audio: true });
|
||||
ms.getTracks().forEach(x => { x.stop() })
|
||||
} catch (e) {
|
||||
console.warn("Enumerate device error::", e)
|
||||
}
|
||||
const mediaDeviceInfos = await navigator.mediaDevices.enumerateDevices();
|
||||
|
||||
const audioInputs = mediaDeviceInfos.filter(x => { return x.kind == "audioinput" })
|
||||
audioInputs.push({
|
||||
deviceId: "none",
|
||||
groupId: "none",
|
||||
kind: "audioinput",
|
||||
label: "none",
|
||||
toJSON: () => { }
|
||||
})
|
||||
audioInputs.push({
|
||||
deviceId: "file",
|
||||
groupId: "file",
|
||||
kind: "audioinput",
|
||||
label: "file",
|
||||
toJSON: () => { }
|
||||
})
|
||||
const audioOutputs = mediaDeviceInfos.filter(x => { return x.kind == "audiooutput" })
|
||||
return [audioInputs, audioOutputs]
|
||||
}
|
||||
export type UseDeviceSettingProps = {
|
||||
clientState: ClientState
|
||||
}
|
||||
|
||||
export type DeviceSettingState = {
|
||||
deviceSetting: JSX.Element;
|
||||
}
|
||||
|
||||
export const useDeviceSetting = (audioContext: AudioContext | null, props: UseDeviceSettingProps): DeviceSettingState => {
|
||||
const [inputAudioDeviceInfo, setInputAudioDeviceInfo] = useState<MediaDeviceInfo[]>([])
|
||||
const [outputAudioDeviceInfo, setOutputAudioDeviceInfo] = useState<MediaDeviceInfo[]>([])
|
||||
|
||||
const [audioInputForGUI, setAudioInputForGUI] = useState<string>("none")
|
||||
const [audioOutputForGUI, setAudioOutputForGUI] = useState<string>("none")
|
||||
const [fileInputEchoback, setFileInputEchoback] = useState<boolean>()//最初のmuteが有効になるように。undefined
|
||||
const { getItem, setItem } = useIndexedDB()
|
||||
|
||||
useEffect(() => {
|
||||
const initialize = async () => {
|
||||
const audioInfo = await reloadDevices()
|
||||
setInputAudioDeviceInfo(audioInfo[0])
|
||||
setOutputAudioDeviceInfo(audioInfo[1])
|
||||
}
|
||||
initialize()
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
if (typeof props.clientState.clientSetting.setting.audioInput == "string") {
|
||||
if (inputAudioDeviceInfo.find(x => {
|
||||
// console.log("COMPARE:", x.deviceId, props.clientState.clientSetting.setting.audioInput)
|
||||
return x.deviceId == props.clientState.clientSetting.setting.audioInput
|
||||
})) {
|
||||
setAudioInputForGUI(props.clientState.clientSetting.setting.audioInput)
|
||||
|
||||
}
|
||||
}
|
||||
}, [inputAudioDeviceInfo, props.clientState.clientSetting.setting.audioInput])
|
||||
|
||||
const audioInputRow = useMemo(() => {
|
||||
return (
|
||||
<div className="body-row split-3-7 left-padding-1 guided">
|
||||
<div className="body-item-title left-padding-1">AudioInput</div>
|
||||
<div className="body-select-container">
|
||||
<select className="body-select" value={audioInputForGUI} onChange={(e) => {
|
||||
setAudioInputForGUI(e.target.value)
|
||||
}}>
|
||||
{
|
||||
inputAudioDeviceInfo.map(x => {
|
||||
return <option key={x.deviceId} value={x.deviceId}>{x.label}</option>
|
||||
})
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}, [inputAudioDeviceInfo, audioInputForGUI, props.clientState.clientSetting.setting.audioInput])
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
if (!audioContext) {
|
||||
return
|
||||
}
|
||||
|
||||
if (audioInputForGUI == "file") {
|
||||
// file selector (audioMediaInputRow)
|
||||
} else {
|
||||
props.clientState.clientSetting.setAudioInput(audioInputForGUI)
|
||||
}
|
||||
}, [audioContext, audioInputForGUI, props.clientState.clientSetting.setAudioInput])
|
||||
|
||||
const audioMediaInputRow = useMemo(() => {
|
||||
if (audioInputForGUI != "file") {
|
||||
return <></>
|
||||
}
|
||||
|
||||
const onFileLoadClicked = async () => {
|
||||
const url = await fileSelectorAsDataURL("")
|
||||
|
||||
// input stream for client.
|
||||
const audio = document.getElementById(AUDIO_ELEMENT_FOR_TEST_CONVERTED) as HTMLAudioElement
|
||||
audio.src = url
|
||||
await audio.play()
|
||||
const src = audioContext!.createMediaElementSource(audio);
|
||||
const dst = audioContext!.createMediaStreamDestination()
|
||||
src.connect(dst)
|
||||
props.clientState.clientSetting.setAudioInput(dst.stream)
|
||||
|
||||
const audio_echo = document.getElementById(AUDIO_ELEMENT_FOR_TEST_CONVERTED_ECHOBACK) as HTMLAudioElement
|
||||
audio_echo.srcObject = dst.stream
|
||||
audio_echo.play()
|
||||
setFileInputEchoback(false)
|
||||
|
||||
// original stream to play.
|
||||
const audio_org = document.getElementById(AUDIO_ELEMENT_FOR_TEST_ORIGINAL) as HTMLAudioElement
|
||||
audio_org.src = url
|
||||
audio_org.pause()
|
||||
|
||||
// audio_org.onplay = () => {
|
||||
// console.log(audioOutputRef.current)
|
||||
// // @ts-ignore
|
||||
// audio_org.setSinkId(audioOutputRef.current)
|
||||
// }
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="body-row split-3-3-4 left-padding-1 guided">
|
||||
<div className="body-item-title"></div>
|
||||
<div className="body-item-text">
|
||||
<div style={{ display: "none" }}>
|
||||
org:<audio id={AUDIO_ELEMENT_FOR_TEST_ORIGINAL} controls></audio>
|
||||
</div>
|
||||
<div>
|
||||
<audio id={AUDIO_ELEMENT_FOR_TEST_CONVERTED} controls></audio>
|
||||
<audio id={AUDIO_ELEMENT_FOR_TEST_CONVERTED_ECHOBACK} controls hidden></audio>
|
||||
</div>
|
||||
</div>
|
||||
<div className="body-button-container">
|
||||
<div className="body-button" onClick={onFileLoadClicked}>load</div>
|
||||
<input type="checkbox" checked={fileInputEchoback} onChange={(e) => { setFileInputEchoback(e.target.checked) }} /> echoback
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}, [audioInputForGUI, props.clientState.clientSetting.setAudioInput, fileInputEchoback])
|
||||
|
||||
|
||||
|
||||
const audioOutputRow = useMemo(() => {
|
||||
return (
|
||||
<div className="body-row split-3-7 left-padding-1 guided">
|
||||
<div className="body-item-title left-padding-1">AudioOutput</div>
|
||||
<div className="body-select-container">
|
||||
<select className="body-select" value={audioOutputForGUI} onChange={(e) => {
|
||||
setAudioOutputForGUI(e.target.value)
|
||||
setItem(INDEXEDDB_KEY_AUDIO_OUTPUT, e.target.value)
|
||||
}}>
|
||||
{
|
||||
outputAudioDeviceInfo.map(x => {
|
||||
return <option key={x.deviceId} value={x.deviceId}>{x.label}</option>
|
||||
})
|
||||
}
|
||||
</select>
|
||||
<audio hidden id={AUDIO_ELEMENT_FOR_PLAY_RESULT}></audio>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}, [outputAudioDeviceInfo, audioOutputForGUI])
|
||||
|
||||
useEffect(() => {
|
||||
[AUDIO_ELEMENT_FOR_PLAY_RESULT, AUDIO_ELEMENT_FOR_TEST_ORIGINAL, AUDIO_ELEMENT_FOR_TEST_CONVERTED_ECHOBACK].forEach(x => {
|
||||
const audio = document.getElementById(x) as HTMLAudioElement
|
||||
if (audio) {
|
||||
if (audioOutputForGUI == "none") {
|
||||
// @ts-ignore
|
||||
audio.setSinkId("")
|
||||
|
||||
} else {
|
||||
// @ts-ignore
|
||||
audio.setSinkId(audioOutputForGUI)
|
||||
}
|
||||
}
|
||||
})
|
||||
}, [audioOutputForGUI])
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
const loadCache = async () => {
|
||||
const key = await getItem(INDEXEDDB_KEY_AUDIO_OUTPUT)
|
||||
if (key) {
|
||||
setAudioOutputForGUI(key as string)
|
||||
}
|
||||
}
|
||||
loadCache()
|
||||
}, [])
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
[AUDIO_ELEMENT_FOR_TEST_CONVERTED_ECHOBACK].forEach(x => {
|
||||
const audio = document.getElementById(x) as HTMLAudioElement
|
||||
if (audio) {
|
||||
audio.volume = fileInputEchoback ? 1 : 0
|
||||
}
|
||||
})
|
||||
}, [fileInputEchoback])
|
||||
|
||||
const deviceSetting = useMemo(() => {
|
||||
return (
|
||||
<>
|
||||
<div className="body-row split-3-7 left-padding-1">
|
||||
<div className="body-sub-section-title">Device Setting</div>
|
||||
<div className="body-select-container">
|
||||
</div>
|
||||
</div>
|
||||
{audioInputRow}
|
||||
{audioMediaInputRow}
|
||||
{audioOutputRow}
|
||||
</>
|
||||
)
|
||||
}, [audioInputRow, audioMediaInputRow, audioOutputRow])
|
||||
|
||||
return {
|
||||
deviceSetting,
|
||||
}
|
||||
}
|
@ -1,118 +0,0 @@
|
||||
import React, { useMemo, useState } from "react"
|
||||
import { ClientState } from "@dannadori/voice-changer-client-js";
|
||||
|
||||
export type UseSpeakerSettingProps = {
|
||||
clientState: ClientState
|
||||
}
|
||||
|
||||
export const useSpeakerSetting = (props: UseSpeakerSettingProps) => {
|
||||
const [editSpeakerTargetId, setEditSpeakerTargetId] = useState<number>(0)
|
||||
const [editSpeakerTargetName, setEditSpeakerTargetName] = useState<string>("")
|
||||
|
||||
const srcIdRow = useMemo(() => {
|
||||
return (
|
||||
<div className="body-row split-3-7 left-padding-1 guided">
|
||||
<div className="body-item-title left-padding-1">Source Speaker Id</div>
|
||||
<div className="body-select-container">
|
||||
<select className="body-select" value={props.clientState.serverSetting.setting.srcId} onChange={(e) => {
|
||||
props.clientState.serverSetting.setSrcId(Number(e.target.value))
|
||||
}}>
|
||||
{
|
||||
props.clientState.clientSetting.setting.speakers.map(x => {
|
||||
return <option key={x.id} value={x.id}>{x.name}({x.id})</option>
|
||||
})
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}, [props.clientState.clientSetting.setting.speakers, props.clientState.serverSetting.setting.srcId, props.clientState.serverSetting.setSrcId])
|
||||
|
||||
const dstIdRow = useMemo(() => {
|
||||
return (
|
||||
<div className="body-row split-3-7 left-padding-1 guided">
|
||||
<div className="body-item-title left-padding-1">Destination Speaker Id</div>
|
||||
<div className="body-select-container">
|
||||
<select className="body-select" value={props.clientState.serverSetting.setting.dstId} onChange={(e) => {
|
||||
props.clientState.serverSetting.setDstId(Number(e.target.value))
|
||||
}}>
|
||||
{
|
||||
props.clientState.clientSetting.setting.speakers.map(x => {
|
||||
return <option key={x.id} value={x.id}>{x.name}({x.id})</option>
|
||||
})
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}, [props.clientState.clientSetting.setting.speakers, props.clientState.serverSetting.setting.dstId, props.clientState.serverSetting.setDstId])
|
||||
|
||||
const editSpeakerIdMappingRow = useMemo(() => {
|
||||
const onSetSpeakerMappingClicked = async () => {
|
||||
const targetId = editSpeakerTargetId
|
||||
const targetName = editSpeakerTargetName
|
||||
const targetSpeaker = props.clientState.clientSetting.setting.speakers.find(x => { return x.id == targetId })
|
||||
if (targetSpeaker) {
|
||||
if (targetName.length == 0) { // Delete
|
||||
const newSpeakers = props.clientState.clientSetting.setting.speakers.filter(x => { return x.id != targetId })
|
||||
props.clientState.clientSetting.setSpeakers(newSpeakers)
|
||||
} else { // Update
|
||||
targetSpeaker.name = targetName
|
||||
props.clientState.clientSetting.setSpeakers([...props.clientState.clientSetting.setting.speakers])
|
||||
}
|
||||
} else {
|
||||
if (targetName.length == 0) { // Noop
|
||||
} else {// add
|
||||
props.clientState.clientSetting.setting.speakers.push({
|
||||
id: targetId,
|
||||
name: targetName
|
||||
})
|
||||
props.clientState.clientSetting.setSpeakers([...props.clientState.clientSetting.setting.speakers])
|
||||
}
|
||||
}
|
||||
}
|
||||
return (
|
||||
<div className="body-row split-3-1-2-4 left-padding-1 guided">
|
||||
<div className="body-item-title left-padding-1">Edit Speaker Mapping</div>
|
||||
<div className="body-input-container">
|
||||
<input type="number" min={1} max={256} step={1} value={editSpeakerTargetId} onChange={(e) => {
|
||||
const id = Number(e.target.value)
|
||||
setEditSpeakerTargetId(id)
|
||||
setEditSpeakerTargetName(props.clientState.clientSetting.setting.speakers.find(x => { return x.id == id })?.name || "")
|
||||
}} />
|
||||
</div>
|
||||
<div className="body-input-container">
|
||||
<input type="text" value={editSpeakerTargetName} onChange={(e) => {
|
||||
setEditSpeakerTargetName(e.target.value)
|
||||
}} />
|
||||
</div>
|
||||
<div className="body-button-container">
|
||||
<div className="body-button" onClick={onSetSpeakerMappingClicked}>set</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}, [props.clientState.clientSetting.setting.speakers, editSpeakerTargetId, editSpeakerTargetName])
|
||||
|
||||
|
||||
const speakerSetting = useMemo(() => {
|
||||
return (
|
||||
<>
|
||||
<div className="body-row split-3-7 left-padding-1">
|
||||
<div className="body-sub-section-title">Speaker Setting</div>
|
||||
<div className="body-select-container">
|
||||
</div>
|
||||
</div>
|
||||
{srcIdRow}
|
||||
{dstIdRow}
|
||||
{editSpeakerIdMappingRow}
|
||||
</>
|
||||
)
|
||||
}, [srcIdRow, dstIdRow, editSpeakerIdMappingRow])
|
||||
|
||||
return {
|
||||
speakerSetting,
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -1,61 +0,0 @@
|
||||
import React, { useMemo } from "react"
|
||||
import { ClientState } from "@dannadori/voice-changer-client-js";
|
||||
|
||||
export type UseConvertSettingProps = {
|
||||
clientState: ClientState
|
||||
}
|
||||
|
||||
export type ConvertSettingState = {
|
||||
convertSetting: JSX.Element;
|
||||
}
|
||||
|
||||
export const useConvertSetting = (props: UseConvertSettingProps): ConvertSettingState => {
|
||||
const inputChunkNumRow = useMemo(() => {
|
||||
return (
|
||||
<div className="body-row split-3-7 left-padding-1 guided">
|
||||
<div className="body-item-title left-padding-1">Input Chunk Num(128sample/chunk)</div>
|
||||
<div className="body-input-container">
|
||||
<input type="number" min={1} max={256} step={1} value={props.clientState.clientSetting.setting.inputChunkNum} onChange={(e) => {
|
||||
props.clientState.clientSetting.setInputChunkNum(Number(e.target.value))
|
||||
}} />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}, [props.clientState.clientSetting.setting.inputChunkNum, props.clientState.clientSetting.setInputChunkNum])
|
||||
|
||||
const gpuRow = useMemo(() => {
|
||||
return (
|
||||
<div className="body-row split-3-7 left-padding-1 guided">
|
||||
<div className="body-item-title left-padding-1">GPU</div>
|
||||
<div className="body-input-container">
|
||||
<input type="number" min={-2} max={5} step={1} value={props.clientState.serverSetting.setting.gpu} onChange={(e) => {
|
||||
props.clientState.serverSetting.setGpu(Number(e.target.value))
|
||||
}} />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}, [props.clientState.serverSetting.setting.gpu, props.clientState.serverSetting.setGpu])
|
||||
|
||||
|
||||
const convertSetting = useMemo(() => {
|
||||
return (
|
||||
<>
|
||||
<div className="body-row split-3-7 left-padding-1">
|
||||
<div className="body-sub-section-title">Converter Setting</div>
|
||||
<div className="body-select-container">
|
||||
</div>
|
||||
</div>
|
||||
{inputChunkNumRow}
|
||||
{gpuRow}
|
||||
|
||||
</>
|
||||
)
|
||||
}, [inputChunkNumRow, gpuRow])
|
||||
|
||||
return {
|
||||
convertSetting,
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -1,294 +0,0 @@
|
||||
import { BufferSize, Protocol, SampleRate, VoiceChangerMode } from "@dannadori/voice-changer-client-js"
|
||||
import React, { useMemo, useState } from "react"
|
||||
import { ClientState } from "@dannadori/voice-changer-client-js";
|
||||
|
||||
|
||||
export type UseAdvancedSettingProps = {
|
||||
clientState: ClientState
|
||||
}
|
||||
|
||||
export type AdvancedSettingState = {
|
||||
advancedSetting: JSX.Element;
|
||||
}
|
||||
|
||||
export const useAdvancedSetting = (props: UseAdvancedSettingProps): AdvancedSettingState => {
|
||||
const [showAdvancedSetting, setShowAdvancedSetting] = useState<boolean>(false)
|
||||
const mmvcServerUrlRow = useMemo(() => {
|
||||
const onSetServerClicked = async () => {
|
||||
const input = document.getElementById("mmvc-server-url") as HTMLInputElement
|
||||
props.clientState.clientSetting.setServerUrl(input.value)
|
||||
}
|
||||
return (
|
||||
<div className="body-row split-3-3-4 left-padding-1 guided">
|
||||
<div className="body-item-title left-padding-1">MMVC Server</div>
|
||||
<div className="body-input-container">
|
||||
<input type="text" defaultValue={props.clientState.clientSetting.setting.mmvcServerUrl} id="mmvc-server-url" className="body-item-input" />
|
||||
</div>
|
||||
<div className="body-button-container">
|
||||
<div className="body-button" onClick={onSetServerClicked}>set</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}, [props.clientState.clientSetting.setting.mmvcServerUrl, props.clientState.clientSetting.setServerUrl])
|
||||
|
||||
const protocolRow = useMemo(() => {
|
||||
const onProtocolChanged = async (val: Protocol) => {
|
||||
props.clientState.clientSetting.setProtocol(val)
|
||||
}
|
||||
return (
|
||||
<div className="body-row split-3-7 left-padding-1 guided">
|
||||
<div className="body-item-title left-padding-1">Protocol</div>
|
||||
<div className="body-select-container">
|
||||
<select className="body-select" value={props.clientState.clientSetting.setting.protocol} onChange={(e) => {
|
||||
onProtocolChanged(e.target.value as
|
||||
Protocol)
|
||||
}}>
|
||||
{
|
||||
Object.values(Protocol).map(x => {
|
||||
return <option key={x} value={x}>{x}</option>
|
||||
})
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}, [props.clientState.clientSetting.setting.protocol, props.clientState.clientSetting.setProtocol])
|
||||
|
||||
|
||||
const sampleRateRow = useMemo(() => {
|
||||
return (
|
||||
<div className="body-row split-3-7 left-padding-1 guided">
|
||||
<div className="body-item-title left-padding-1">Sample Rate</div>
|
||||
<div className="body-select-container">
|
||||
<select className="body-select" value={props.clientState.clientSetting.setting.sampleRate} onChange={(e) => {
|
||||
props.clientState.clientSetting.setSampleRate(Number(e.target.value) as SampleRate)
|
||||
}}>
|
||||
{
|
||||
Object.values(SampleRate).map(x => {
|
||||
return <option key={x} value={x}>{x}</option>
|
||||
})
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}, [props.clientState.clientSetting.setting.sampleRate, props.clientState.clientSetting.setSampleRate])
|
||||
|
||||
const bufferSizeRow = useMemo(() => {
|
||||
return (
|
||||
|
||||
<div className="body-row split-3-7 left-padding-1 guided">
|
||||
<div className="body-item-title left-padding-1">Buffer Size</div>
|
||||
<div className="body-select-container">
|
||||
<select className="body-select" value={props.clientState.clientSetting.setting.bufferSize} onChange={(e) => {
|
||||
props.clientState.clientSetting.setBufferSize(Number(e.target.value) as BufferSize)
|
||||
}}>
|
||||
{
|
||||
Object.values(BufferSize).map(x => {
|
||||
return <option key={x} value={x}>{x}</option>
|
||||
})
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}, [props.clientState.clientSetting.setting.bufferSize, props.clientState.clientSetting.setBufferSize])
|
||||
|
||||
const convertChunkNumRow = useMemo(() => {
|
||||
return (
|
||||
|
||||
<div className="body-row split-3-7 left-padding-1 guided">
|
||||
<div className="body-item-title left-padding-1">Convert Chunk Num(128sample/chunk)</div>
|
||||
<div className="body-input-container">
|
||||
<input type="number" min={1} max={256} step={1} value={props.clientState.serverSetting.setting.convertChunkNum} onChange={(e) => {
|
||||
props.clientState.serverSetting.setConvertChunkNum(Number(e.target.value))
|
||||
}} />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}, [props.clientState.serverSetting.setting.convertChunkNum, props.clientState.serverSetting.setConvertChunkNum])
|
||||
|
||||
const minConvertSizeRow = useMemo(() => {
|
||||
return (
|
||||
|
||||
<div className="body-row split-3-7 left-padding-1 guided">
|
||||
<div className="body-item-title left-padding-1">Min Convert Size(byte)</div>
|
||||
<div className="body-input-container">
|
||||
<input type="number" min={0} max={8196} step={8196} value={props.clientState.serverSetting.setting.minConvertSize} onChange={(e) => {
|
||||
props.clientState.serverSetting.setMinConvertSize(Number(e.target.value))
|
||||
}} />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}, [props.clientState.serverSetting.setting.minConvertSize, props.clientState.serverSetting.setMinConvertSize])
|
||||
|
||||
const crossFadeOverlapRateRow = useMemo(() => {
|
||||
return (
|
||||
<div className="body-row split-3-7 left-padding-1 guided">
|
||||
<div className="body-item-title left-padding-1">Cross Fade Overlap Rate</div>
|
||||
<div className="body-input-container">
|
||||
<input type="number" min={0.1} max={1} step={0.1} value={props.clientState.serverSetting.setting.crossFadeOverlapRate} onChange={(e) => {
|
||||
props.clientState.serverSetting.setCrossFadeOverlapRate(Number(e.target.value))
|
||||
}} />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}, [props.clientState.serverSetting.setting.crossFadeOverlapRate, props.clientState.serverSetting.setCrossFadeOverlapRate])
|
||||
|
||||
const crossFadeOffsetRateRow = useMemo(() => {
|
||||
return (
|
||||
<div className="body-row split-3-7 left-padding-1 guided">
|
||||
<div className="body-item-title left-padding-1">Cross Fade Offset Rate</div>
|
||||
<div className="body-input-container">
|
||||
<input type="number" min={0} max={1} step={0.1} value={props.clientState.serverSetting.setting.crossFadeOffsetRate} onChange={(e) => {
|
||||
props.clientState.serverSetting.setCrossFadeOffsetRate(Number(e.target.value))
|
||||
}} />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}, [props.clientState.serverSetting.setting.crossFadeOffsetRate, props.clientState.serverSetting.setCrossFadeOffsetRate])
|
||||
|
||||
const crossFadeEndRateRow = useMemo(() => {
|
||||
return (
|
||||
<div className="body-row split-3-7 left-padding-1 guided">
|
||||
<div className="body-item-title left-padding-1">Cross Fade End Rate</div>
|
||||
<div className="body-input-container">
|
||||
<input type="number" min={0} max={1} step={0.1} value={props.clientState.serverSetting.setting.crossFadeEndRate} onChange={(e) => {
|
||||
props.clientState.serverSetting.setCrossFadeEndRate(Number(e.target.value))
|
||||
}} />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}, [props.clientState.serverSetting.setting.crossFadeEndRate, props.clientState.serverSetting.setCrossFadeEndRate])
|
||||
|
||||
|
||||
const vfForceDisableRow = useMemo(() => {
|
||||
return (
|
||||
<div className="body-row split-3-3-4 left-padding-1 guided">
|
||||
<div className="body-item-title left-padding-1 ">VF Disabled</div>
|
||||
<div>
|
||||
<input type="checkbox" checked={props.clientState.clientSetting.setting.forceVfDisable} onChange={(e) => {
|
||||
props.clientState.clientSetting.setVfForceDisabled(e.target.checked)
|
||||
}} />
|
||||
</div>
|
||||
<div className="body-button-container">
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}, [props.clientState.clientSetting.setting.forceVfDisable, props.clientState.clientSetting.setVfForceDisabled])
|
||||
|
||||
const voiceChangeModeRow = useMemo(() => {
|
||||
return (
|
||||
<div className="body-row split-3-7 left-padding-1 guided">
|
||||
<div className="body-item-title left-padding-1 ">Voice Change Mode</div>
|
||||
<div className="body-select-container">
|
||||
<select className="body-select" value={props.clientState.clientSetting.setting.voiceChangerMode} onChange={(e) => {
|
||||
props.clientState.clientSetting.setVoiceChangerMode(e.target.value as VoiceChangerMode)
|
||||
}}>
|
||||
{
|
||||
Object.values(VoiceChangerMode).map(x => {
|
||||
return <option key={x} value={x}>{x}</option>
|
||||
})
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}, [props.clientState.clientSetting.setting.voiceChangerMode, props.clientState.clientSetting.setVoiceChangerMode])
|
||||
|
||||
|
||||
|
||||
const workletSettingRow = useMemo(() => {
|
||||
return (
|
||||
<>
|
||||
|
||||
<div className="body-row split-3-7 left-padding-1 guided">
|
||||
<div className="body-item-title left-padding-1">Trancate Num</div>
|
||||
<div className="body-input-container">
|
||||
<input type="number" min={50} max={300} step={1} value={props.clientState.workletSetting.setting.numTrancateTreshold} onChange={(e) => {
|
||||
props.clientState.workletSetting.setSetting({
|
||||
...props.clientState.workletSetting.setting,
|
||||
numTrancateTreshold: Number(e.target.value)
|
||||
})
|
||||
}} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="body-row split-3-7 left-padding-1 guided">
|
||||
<div className="body-item-title left-padding-1">Trancate Vol</div>
|
||||
<div className="body-input-container">
|
||||
<input type="number" min={0.0001} max={0.0009} step={0.0001} value={props.clientState.workletSetting.setting.volTrancateThreshold} onChange={(e) => {
|
||||
props.clientState.workletSetting.setSetting({
|
||||
...props.clientState.workletSetting.setting,
|
||||
volTrancateThreshold: Number(e.target.value)
|
||||
})
|
||||
}} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="body-row split-3-7 left-padding-1 guided">
|
||||
<div className="body-item-title left-padding-1">Trancate Vol Length</div>
|
||||
<div className="body-input-container">
|
||||
<input type="number" min={16} max={128} step={1} value={props.clientState.workletSetting.setting.volTrancateLength} onChange={(e) => {
|
||||
props.clientState.workletSetting.setSetting({
|
||||
...props.clientState.workletSetting.setting,
|
||||
volTrancateLength: Number(e.target.value)
|
||||
})
|
||||
}} />
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}, [props.clientState.workletSetting.setting, props.clientState.workletSetting.setSetting])
|
||||
|
||||
|
||||
const advanceSettingContent = useMemo(() => {
|
||||
if (!showAdvancedSetting) return <></>
|
||||
return (
|
||||
<>
|
||||
<div className="body-row divider"></div>
|
||||
{mmvcServerUrlRow}
|
||||
{protocolRow}
|
||||
<div className="body-row divider"></div>
|
||||
{sampleRateRow}
|
||||
{bufferSizeRow}
|
||||
<div className="body-row divider"></div>
|
||||
|
||||
{convertChunkNumRow}
|
||||
{minConvertSizeRow}
|
||||
{crossFadeOverlapRateRow}
|
||||
{crossFadeOffsetRateRow}
|
||||
{crossFadeEndRateRow}
|
||||
<div className="body-row divider"></div>
|
||||
{vfForceDisableRow}
|
||||
{voiceChangeModeRow}
|
||||
<div className="body-row divider"></div>
|
||||
{workletSettingRow}
|
||||
<div className="body-row divider"></div>
|
||||
</>
|
||||
)
|
||||
}, [showAdvancedSetting, mmvcServerUrlRow, protocolRow, sampleRateRow, bufferSizeRow, convertChunkNumRow, minConvertSizeRow, crossFadeOverlapRateRow, crossFadeOffsetRateRow, crossFadeEndRateRow, vfForceDisableRow, voiceChangeModeRow, workletSettingRow])
|
||||
|
||||
|
||||
const advancedSetting = useMemo(() => {
|
||||
return (
|
||||
<>
|
||||
<div className="body-row split-3-7 left-padding-1">
|
||||
<div className="body-sub-section-title">Advanced Setting</div>
|
||||
<div>
|
||||
<input type="checkbox" checked={showAdvancedSetting} onChange={(e) => {
|
||||
setShowAdvancedSetting(e.target.checked)
|
||||
}} /> show
|
||||
</div>
|
||||
</div>
|
||||
{advanceSettingContent}
|
||||
</>
|
||||
)
|
||||
}, [showAdvancedSetting, advanceSettingContent])
|
||||
|
||||
return {
|
||||
advancedSetting,
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -1,109 +0,0 @@
|
||||
import React, { useMemo, useState } from "react"
|
||||
import { ClientState } from "@dannadori/voice-changer-client-js";
|
||||
|
||||
export type UseServerControlProps = {
|
||||
clientState: ClientState
|
||||
}
|
||||
|
||||
export const useServerControl = (props: UseServerControlProps) => {
|
||||
const [isStarted, setIsStarted] = useState<boolean>(false)
|
||||
|
||||
const startButtonRow = useMemo(() => {
|
||||
const onStartClicked = async () => {
|
||||
setIsStarted(true)
|
||||
await props.clientState.clientSetting.start()
|
||||
}
|
||||
const onStopClicked = async () => {
|
||||
setIsStarted(false)
|
||||
console.log("stop click1")
|
||||
await props.clientState.clientSetting.stop()
|
||||
console.log("stop click2")
|
||||
}
|
||||
const startClassName = isStarted ? "body-button-active" : "body-button-stanby"
|
||||
const stopClassName = isStarted ? "body-button-stanby" : "body-button-active"
|
||||
|
||||
return (
|
||||
<div className="body-row split-3-3-4 left-padding-1 guided">
|
||||
<div className="body-item-title left-padding-1">Start</div>
|
||||
<div className="body-button-container">
|
||||
<div onClick={onStartClicked} className={startClassName}>start</div>
|
||||
<div onClick={onStopClicked} className={stopClassName}>stop</div>
|
||||
</div>
|
||||
<div className="body-input-container">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
)
|
||||
}, [isStarted, props.clientState.clientSetting.start, props.clientState.clientSetting.stop])
|
||||
|
||||
const performanceRow = useMemo(() => {
|
||||
return (
|
||||
<>
|
||||
<div className="body-row split-3-1-1-1-4 left-padding-1 guided">
|
||||
<div className="body-item-title left-padding-1">monitor:</div>
|
||||
<div className="body-item-text">vol<span className="body-item-text-small">(rms)</span></div>
|
||||
<div className="body-item-text">buf<span className="body-item-text-small">(ms)</span></div>
|
||||
<div className="body-item-text">res<span className="body-item-text-small">(ms)</span></div>
|
||||
<div className="body-item-text"></div>
|
||||
</div>
|
||||
<div className="body-row split-3-1-1-1-4 left-padding-1 guided">
|
||||
<div className="body-item-title left-padding-1"></div>
|
||||
<div className="body-item-text">{props.clientState.volume.toFixed(4)}</div>
|
||||
<div className="body-item-text">{props.clientState.bufferingTime}</div>
|
||||
<div className="body-item-text">{props.clientState.responseTime}</div>
|
||||
<div className="body-item-text"></div>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}, [props.clientState.volume, props.clientState.bufferingTime, props.clientState.responseTime])
|
||||
|
||||
|
||||
|
||||
const infoRow = useMemo(() => {
|
||||
const onReloadClicked = async () => {
|
||||
const info = await props.clientState.getInfo()
|
||||
console.log("info", info)
|
||||
}
|
||||
return (
|
||||
<>
|
||||
<div className="body-row split-3-3-4 left-padding-1 guided">
|
||||
<div className="body-item-title left-padding-1">Model Info:</div>
|
||||
<div className="body-item-text">
|
||||
<span className="body-item-text-item">{props.clientState.serverSetting.serverInfo?.configFile || ""}</span>
|
||||
<span className="body-item-text-item">{props.clientState.serverSetting.serverInfo?.pyTorchModelFile || ""}</span>
|
||||
<span className="body-item-text-item">{props.clientState.serverSetting.serverInfo?.onnxModelFile || ""}</span>
|
||||
|
||||
|
||||
</div>
|
||||
<div className="body-button-container">
|
||||
<div className="body-button" onClick={onReloadClicked}>reload</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}, [props.clientState.getInfo, props.clientState.serverSetting.serverInfo])
|
||||
|
||||
|
||||
|
||||
const serverControl = useMemo(() => {
|
||||
return (
|
||||
<>
|
||||
<div className="body-row split-3-7 left-padding-1">
|
||||
<div className="body-sub-section-title">Server Control</div>
|
||||
<div className="body-select-container">
|
||||
</div>
|
||||
</div>
|
||||
{startButtonRow}
|
||||
{performanceRow}
|
||||
{infoRow}
|
||||
</>
|
||||
)
|
||||
}, [startButtonRow, performanceRow, infoRow])
|
||||
|
||||
return {
|
||||
serverControl,
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
37
client/demo/src/components/101_HeaderButton.tsx
Normal file
@ -0,0 +1,37 @@
|
||||
import { IconName, IconPrefix } from "@fortawesome/free-regular-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import React, { useMemo } from "react";
|
||||
import { StateControlCheckbox } from "../hooks/useStateControlCheckbox";
|
||||
|
||||
export const AnimationTypes = {
|
||||
colored: "colored",
|
||||
spinner: "spinner",
|
||||
} as const;
|
||||
export type AnimationTypes = typeof AnimationTypes[keyof typeof AnimationTypes];
|
||||
|
||||
export type HeaderButtonProps = {
|
||||
stateControlCheckbox: StateControlCheckbox;
|
||||
tooltip: string;
|
||||
onIcon: [IconPrefix, IconName];
|
||||
offIcon: [IconPrefix, IconName];
|
||||
animation: AnimationTypes;
|
||||
tooltipClass?: string;
|
||||
};
|
||||
|
||||
export const HeaderButton = (props: HeaderButtonProps) => {
|
||||
const headerButton = useMemo(() => {
|
||||
const tooltipClass = props.tooltipClass || "tooltip-bottom";
|
||||
return (
|
||||
<div className={`rotate-button-container ${tooltipClass}`} data-tooltip={props.tooltip}>
|
||||
{props.stateControlCheckbox.trigger}
|
||||
<label htmlFor={props.stateControlCheckbox.className} className="rotate-lable">
|
||||
<div className={props.animation}>
|
||||
<FontAwesomeIcon icon={props.onIcon} className="spin-on" />
|
||||
<FontAwesomeIcon icon={props.offIcon} className="spin-off" />
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
);
|
||||
}, []);
|
||||
return headerButton;
|
||||
};
|
395
client/demo/src/components/demo/001_GuiStateProvider.tsx
Normal file
@ -0,0 +1,395 @@
|
||||
import React, { useContext, useEffect, useState, useRef } from "react";
|
||||
import { ReactNode } from "react";
|
||||
import { useAppRoot } from "../../001_provider/001_AppRootProvider";
|
||||
import { StateControlCheckbox, useStateControlCheckbox } from "../../hooks/useStateControlCheckbox";
|
||||
import { useAppState } from "../../001_provider/001_AppStateProvider";
|
||||
|
||||
export const OpenServerControlCheckbox = "open-server-control-checkbox";
|
||||
export const OpenModelSettingCheckbox = "open-model-setting-checkbox";
|
||||
export const OpenDeviceSettingCheckbox = "open-device-setting-checkbox";
|
||||
export const OpenQualityControlCheckbox = "open-quality-control-checkbox";
|
||||
export const OpenSpeakerSettingCheckbox = "open-speaker-setting-checkbox";
|
||||
export const OpenConverterSettingCheckbox = "open-converter-setting-checkbox";
|
||||
export const OpenAdvancedSettingCheckbox = "open-advanced-setting-checkbox";
|
||||
export const OpenLabCheckbox = "open-lab-checkbox";
|
||||
|
||||
export const OpenLicenseDialogCheckbox = "open-license-dialog-checkbox";
|
||||
export const OpenWaitingDialogCheckbox = "open-waiting-dialog-checkbox";
|
||||
export const OpenStartingNoticeDialogCheckbox = "open-starting-notice-dialog-checkbox";
|
||||
export const OpenModelSlotManagerDialogCheckbox = "open-model-slot-manager-dialog-checkbox";
|
||||
export const OpenMergeLabDialogCheckbox = "open-merge-lab-dialog-checkbox";
|
||||
export const OpenAdvancedSettingDialogCheckbox = "open-advanced-setting-dialog-checkbox";
|
||||
export const OpenGetServerInformationDialogCheckbox = "open-get-server-information-dialog-checkbox";
|
||||
export const OpenGetClientInformationDialogCheckbox = "open-get-client-information-dialog-checkbox";
|
||||
export const OpenEnablePassThroughDialogCheckbox = "open-enable-pass-through-dialog-checkbox";
|
||||
|
||||
export const OpenTextInputDialogCheckbox = "open-text-input-dialog-checkbox";
|
||||
export const OpenShowLicenseDialogCheckbox = "open-show-license-dialog-checkbox";
|
||||
|
||||
type Props = {
|
||||
children: ReactNode;
|
||||
};
|
||||
|
||||
export type StateControls = {
|
||||
openServerControlCheckbox: StateControlCheckbox;
|
||||
openModelSettingCheckbox: StateControlCheckbox;
|
||||
openDeviceSettingCheckbox: StateControlCheckbox;
|
||||
openQualityControlCheckbox: StateControlCheckbox;
|
||||
openSpeakerSettingCheckbox: StateControlCheckbox;
|
||||
openConverterSettingCheckbox: StateControlCheckbox;
|
||||
openAdvancedSettingCheckbox: StateControlCheckbox;
|
||||
openLabCheckbox: StateControlCheckbox;
|
||||
|
||||
showWaitingCheckbox: StateControlCheckbox;
|
||||
showStartingNoticeCheckbox: StateControlCheckbox;
|
||||
showModelSlotManagerCheckbox: StateControlCheckbox;
|
||||
|
||||
showMergeLabCheckbox: StateControlCheckbox;
|
||||
showAdvancedSettingCheckbox: StateControlCheckbox;
|
||||
showGetServerInformationCheckbox: StateControlCheckbox;
|
||||
showGetClientInformationCheckbox: StateControlCheckbox;
|
||||
showEnablePassThroughDialogCheckbox: StateControlCheckbox;
|
||||
showTextInputCheckbox: StateControlCheckbox;
|
||||
showLicenseCheckbox: StateControlCheckbox;
|
||||
};
|
||||
|
||||
type GuiStateAndMethod = {
|
||||
stateControls: StateControls;
|
||||
isConverting: boolean;
|
||||
isAnalyzing: boolean;
|
||||
showPyTorchModelUpload: boolean;
|
||||
setIsConverting: (val: boolean) => void;
|
||||
setIsAnalyzing: (val: boolean) => void;
|
||||
setShowPyTorchModelUpload: (val: boolean) => void;
|
||||
|
||||
reloadDeviceInfo: () => Promise<void>;
|
||||
inputAudioDeviceInfo: MediaDeviceInfo[];
|
||||
outputAudioDeviceInfo: MediaDeviceInfo[];
|
||||
audioInputForGUI: string;
|
||||
audioOutputForGUI: string;
|
||||
audioMonitorForGUI: string;
|
||||
fileInputEchoback: boolean | undefined;
|
||||
shareScreenEnabled: boolean;
|
||||
audioOutputForAnalyzer: string;
|
||||
setInputAudioDeviceInfo: (val: MediaDeviceInfo[]) => void;
|
||||
setOutputAudioDeviceInfo: (val: MediaDeviceInfo[]) => void;
|
||||
setAudioInputForGUI: (val: string) => void;
|
||||
setAudioOutputForGUI: (val: string) => void;
|
||||
setAudioMonitorForGUI: (val: string) => void;
|
||||
setFileInputEchoback: (val: boolean) => void;
|
||||
setShareScreenEnabled: (val: boolean) => void;
|
||||
setAudioOutputForAnalyzer: (val: string) => void;
|
||||
|
||||
modelSlotNum: number;
|
||||
setModelSlotNum: (val: number) => void;
|
||||
|
||||
textInputResolve: TextInputResolveType | null;
|
||||
setTextInputResolve: (val: TextInputResolveType | null) => void;
|
||||
|
||||
// for Beatrice
|
||||
beatriceJVSSpeakerId: number;
|
||||
beatriceJVSSpeakerPitch: number;
|
||||
setBeatriceJVSSpeakerId: (id: number) => void;
|
||||
setBeatriceJVSSpeakerPitch: (pitch: number) => void;
|
||||
};
|
||||
|
||||
const GuiStateContext = React.createContext<GuiStateAndMethod | null>(null);
|
||||
export const useGuiState = (): GuiStateAndMethod => {
|
||||
const state = useContext(GuiStateContext);
|
||||
if (!state) {
|
||||
throw new Error("useGuiState must be used within GuiStateProvider");
|
||||
}
|
||||
return state;
|
||||
};
|
||||
|
||||
type TextInputResolveType = {
|
||||
resolve: ((value: string | PromiseLike<string>) => void) | null;
|
||||
};
|
||||
|
||||
export const GuiStateProvider = ({ children }: Props) => {
|
||||
const { appGuiSettingState } = useAppRoot();
|
||||
const { serverSetting } = useAppState();
|
||||
const [isConverting, setIsConverting] = useState<boolean>(false);
|
||||
const [isAnalyzing, setIsAnalyzing] = useState<boolean>(false);
|
||||
const [modelSlotNum, setModelSlotNum] = useState<number>(0);
|
||||
|
||||
const [showPyTorchModelUpload, setShowPyTorchModelUpload] = useState<boolean>(false);
|
||||
|
||||
const [inputAudioDeviceInfo, setInputAudioDeviceInfo] = useState<MediaDeviceInfo[]>([]);
|
||||
const [outputAudioDeviceInfo, setOutputAudioDeviceInfo] = useState<MediaDeviceInfo[]>([]);
|
||||
const [audioInputForGUI, setAudioInputForGUI] = useState<string>("none");
|
||||
const [audioOutputForGUI, setAudioOutputForGUI] = useState<string>("none");
|
||||
const [audioMonitorForGUI, setAudioMonitorForGUI] = useState<string>("none");
|
||||
const [fileInputEchoback, setFileInputEchoback] = useState<boolean>(false); //最初のmuteが有効になるように。undefined <-- ??? falseしておけばよさそう。undefinedだとwarningがでる。
|
||||
const [shareScreenEnabled, setShareScreenEnabled] = useState<boolean>(false);
|
||||
const [audioOutputForAnalyzer, setAudioOutputForAnalyzer] = useState<string>("default");
|
||||
|
||||
const [textInputResolve, setTextInputResolve] = useState<TextInputResolveType | null>(null);
|
||||
|
||||
const [beatriceJVSSpeakerId, setBeatriceJVSSpeakerId] = useState<number>(1);
|
||||
const [beatriceJVSSpeakerPitch, setBeatriceJVSSpeakerPitch] = useState<number>(0);
|
||||
|
||||
const checkDeviceAvailable = useRef<boolean>(false);
|
||||
|
||||
const _reloadDeviceInfo = async () => {
|
||||
// デバイスチェックの空振り
|
||||
if (checkDeviceAvailable.current == false) {
|
||||
try {
|
||||
const ms = await navigator.mediaDevices.getUserMedia({ video: false, audio: true });
|
||||
ms.getTracks().forEach((x) => {
|
||||
x.stop();
|
||||
});
|
||||
checkDeviceAvailable.current = true;
|
||||
} catch (e) {
|
||||
console.warn("Enumerate device error::", e);
|
||||
}
|
||||
}
|
||||
const mediaDeviceInfos = await navigator.mediaDevices.enumerateDevices();
|
||||
|
||||
const audioInputs = mediaDeviceInfos.filter((x) => {
|
||||
return x.kind == "audioinput";
|
||||
});
|
||||
audioInputs.push({
|
||||
deviceId: "none",
|
||||
groupId: "none",
|
||||
kind: "audioinput",
|
||||
label: "none",
|
||||
toJSON: () => {},
|
||||
});
|
||||
audioInputs.push({
|
||||
deviceId: "file",
|
||||
groupId: "file",
|
||||
kind: "audioinput",
|
||||
label: "file",
|
||||
toJSON: () => {},
|
||||
});
|
||||
audioInputs.push({
|
||||
deviceId: "screen",
|
||||
groupId: "screen",
|
||||
kind: "audioinput",
|
||||
label: "system(only win)",
|
||||
toJSON: () => {},
|
||||
});
|
||||
const audioOutputs = mediaDeviceInfos.filter((x) => {
|
||||
return x.kind == "audiooutput";
|
||||
});
|
||||
audioOutputs.push({
|
||||
deviceId: "none",
|
||||
groupId: "none",
|
||||
kind: "audiooutput",
|
||||
label: "none",
|
||||
toJSON: () => {},
|
||||
});
|
||||
// audioOutputs.push({
|
||||
// deviceId: "record",
|
||||
// groupId: "record",
|
||||
// kind: "audiooutput",
|
||||
// label: "record",
|
||||
// toJSON: () => { }
|
||||
// })
|
||||
return [audioInputs, audioOutputs];
|
||||
};
|
||||
|
||||
const reloadDeviceInfo = async () => {
|
||||
const audioInfo = await _reloadDeviceInfo();
|
||||
setInputAudioDeviceInfo(audioInfo[0]);
|
||||
setOutputAudioDeviceInfo(audioInfo[1]);
|
||||
};
|
||||
|
||||
// useEffect(() => {
|
||||
// const audioInitialize = async () => {
|
||||
// await reloadDeviceInfo();
|
||||
// };
|
||||
// audioInitialize();
|
||||
// }, []);
|
||||
|
||||
useEffect(() => {
|
||||
let isMounted = true;
|
||||
|
||||
// デバイスのポーリングを再帰的に実行する関数
|
||||
const pollDevices = async () => {
|
||||
const checkDeviceDiff = (knownDeviceIds: Set<string>, newDeviceIds: Set<string>) => {
|
||||
const deleted = new Set([...knownDeviceIds].filter((x) => !newDeviceIds.has(x)));
|
||||
const added = new Set([...newDeviceIds].filter((x) => !knownDeviceIds.has(x)));
|
||||
return { deleted, added };
|
||||
};
|
||||
try {
|
||||
const audioInfo = await _reloadDeviceInfo();
|
||||
|
||||
const knownAudioinputIds = new Set(inputAudioDeviceInfo.map((x) => x.deviceId));
|
||||
const newAudioinputIds = new Set(audioInfo[0].map((x) => x.deviceId));
|
||||
|
||||
const knownAudiooutputIds = new Set(outputAudioDeviceInfo.map((x) => x.deviceId));
|
||||
const newAudiooutputIds = new Set(audioInfo[1].map((x) => x.deviceId));
|
||||
|
||||
const audioInputDiff = checkDeviceDiff(knownAudioinputIds, newAudioinputIds);
|
||||
const audioOutputDiff = checkDeviceDiff(knownAudiooutputIds, newAudiooutputIds);
|
||||
|
||||
if (audioInputDiff.deleted.size > 0 || audioInputDiff.added.size > 0) {
|
||||
console.log(`deleted input device: ${[...audioInputDiff.deleted]}`);
|
||||
console.log(`added input device: ${[...audioInputDiff.added]}`);
|
||||
setInputAudioDeviceInfo(audioInfo[0]);
|
||||
}
|
||||
if (audioOutputDiff.deleted.size > 0 || audioOutputDiff.added.size > 0) {
|
||||
console.log(`deleted output device: ${[...audioOutputDiff.deleted]}`);
|
||||
console.log(`added output device: ${[...audioOutputDiff.added]}`);
|
||||
setOutputAudioDeviceInfo(audioInfo[1]);
|
||||
}
|
||||
|
||||
if (isMounted) {
|
||||
setTimeout(pollDevices, 1000 * 3);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("An error occurred during enumeration of devices:", err);
|
||||
}
|
||||
};
|
||||
|
||||
pollDevices();
|
||||
return () => {
|
||||
isMounted = false;
|
||||
};
|
||||
}, [inputAudioDeviceInfo, outputAudioDeviceInfo]);
|
||||
|
||||
// (1) Controller Switch
|
||||
const openServerControlCheckbox = useStateControlCheckbox(OpenServerControlCheckbox);
|
||||
const openModelSettingCheckbox = useStateControlCheckbox(OpenModelSettingCheckbox);
|
||||
const openDeviceSettingCheckbox = useStateControlCheckbox(OpenDeviceSettingCheckbox);
|
||||
const openQualityControlCheckbox = useStateControlCheckbox(OpenQualityControlCheckbox);
|
||||
const openSpeakerSettingCheckbox = useStateControlCheckbox(OpenSpeakerSettingCheckbox);
|
||||
const openConverterSettingCheckbox = useStateControlCheckbox(OpenConverterSettingCheckbox);
|
||||
const openAdvancedSettingCheckbox = useStateControlCheckbox(OpenAdvancedSettingCheckbox);
|
||||
const openLabCheckbox = useStateControlCheckbox(OpenLabCheckbox);
|
||||
|
||||
const showWaitingCheckbox = useStateControlCheckbox(OpenWaitingDialogCheckbox);
|
||||
const showStartingNoticeCheckbox = useStateControlCheckbox(OpenStartingNoticeDialogCheckbox);
|
||||
const showModelSlotManagerCheckbox = useStateControlCheckbox(OpenModelSlotManagerDialogCheckbox);
|
||||
const showMergeLabCheckbox = useStateControlCheckbox(OpenMergeLabDialogCheckbox);
|
||||
const showAdvancedSettingCheckbox = useStateControlCheckbox(OpenAdvancedSettingDialogCheckbox);
|
||||
const showGetServerInformationCheckbox = useStateControlCheckbox(OpenGetServerInformationDialogCheckbox);
|
||||
const showGetClientInformationCheckbox = useStateControlCheckbox(OpenGetClientInformationDialogCheckbox);
|
||||
const showEnablePassThroughDialogCheckbox = useStateControlCheckbox(OpenEnablePassThroughDialogCheckbox);
|
||||
|
||||
const showTextInputCheckbox = useStateControlCheckbox(OpenTextInputDialogCheckbox);
|
||||
const showLicenseCheckbox = useStateControlCheckbox(OpenShowLicenseDialogCheckbox);
|
||||
|
||||
useEffect(() => {
|
||||
openServerControlCheckbox.updateState(true);
|
||||
openModelSettingCheckbox.updateState(false);
|
||||
openDeviceSettingCheckbox.updateState(true);
|
||||
openSpeakerSettingCheckbox.updateState(true);
|
||||
openConverterSettingCheckbox.updateState(true);
|
||||
openQualityControlCheckbox.updateState(false);
|
||||
openLabCheckbox.updateState(false);
|
||||
openAdvancedSettingCheckbox.updateState(false);
|
||||
|
||||
showWaitingCheckbox.updateState(false);
|
||||
|
||||
showStartingNoticeCheckbox.updateState(false);
|
||||
showModelSlotManagerCheckbox.updateState(false);
|
||||
showMergeLabCheckbox.updateState(false);
|
||||
showAdvancedSettingCheckbox.updateState(false);
|
||||
showGetServerInformationCheckbox.updateState(false);
|
||||
showGetClientInformationCheckbox.updateState(false);
|
||||
showEnablePassThroughDialogCheckbox.updateState(false);
|
||||
|
||||
showTextInputCheckbox.updateState(false);
|
||||
showLicenseCheckbox.updateState(false);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const show = () => {
|
||||
// const lang = window.navigator.language
|
||||
// const edition = appGuiSettingState.edition
|
||||
// console.log("appGuiSettingState.edition", appGuiSettingState.edition, lang)
|
||||
// if ((edition == "onnxdirectML-cuda" || edition == "") && lang == "ja") {
|
||||
// return
|
||||
// }
|
||||
|
||||
document.getElementById("dialog")?.classList.add("dialog-container-show");
|
||||
showStartingNoticeCheckbox.updateState(true);
|
||||
document.getElementById("dialog2")?.classList.add("dialog-container-show");
|
||||
};
|
||||
setTimeout(show);
|
||||
}, [appGuiSettingState.edition]);
|
||||
|
||||
useEffect(() => {
|
||||
let dstId;
|
||||
if (beatriceJVSSpeakerPitch == 0) {
|
||||
dstId = (beatriceJVSSpeakerId - 1) * 5;
|
||||
} else if (beatriceJVSSpeakerPitch == 1) {
|
||||
dstId = (beatriceJVSSpeakerId - 1) * 5 + 1;
|
||||
} else if (beatriceJVSSpeakerPitch == 2) {
|
||||
dstId = (beatriceJVSSpeakerId - 1) * 5 + 2;
|
||||
} else if (beatriceJVSSpeakerPitch == -1) {
|
||||
dstId = (beatriceJVSSpeakerId - 1) * 5 + 3;
|
||||
} else if (beatriceJVSSpeakerPitch == -2) {
|
||||
dstId = (beatriceJVSSpeakerId - 1) * 5 + 4;
|
||||
} else {
|
||||
throw new Error(`invalid beatriceJVSSpeakerPitch speaker:${beatriceJVSSpeakerId} pitch:${beatriceJVSSpeakerPitch}`);
|
||||
}
|
||||
serverSetting.updateServerSettings({ ...serverSetting.serverSetting, dstId: dstId });
|
||||
}, [beatriceJVSSpeakerId, beatriceJVSSpeakerPitch]);
|
||||
|
||||
const providerValue: GuiStateAndMethod = {
|
||||
stateControls: {
|
||||
openServerControlCheckbox,
|
||||
openModelSettingCheckbox,
|
||||
openDeviceSettingCheckbox,
|
||||
openQualityControlCheckbox,
|
||||
openSpeakerSettingCheckbox,
|
||||
openConverterSettingCheckbox,
|
||||
openAdvancedSettingCheckbox,
|
||||
openLabCheckbox,
|
||||
|
||||
showWaitingCheckbox,
|
||||
showStartingNoticeCheckbox,
|
||||
showModelSlotManagerCheckbox,
|
||||
|
||||
showMergeLabCheckbox,
|
||||
showAdvancedSettingCheckbox,
|
||||
showGetServerInformationCheckbox,
|
||||
showGetClientInformationCheckbox,
|
||||
showEnablePassThroughDialogCheckbox,
|
||||
|
||||
showTextInputCheckbox,
|
||||
showLicenseCheckbox,
|
||||
},
|
||||
isConverting,
|
||||
setIsConverting,
|
||||
isAnalyzing,
|
||||
setIsAnalyzing,
|
||||
showPyTorchModelUpload,
|
||||
setShowPyTorchModelUpload,
|
||||
|
||||
reloadDeviceInfo,
|
||||
inputAudioDeviceInfo,
|
||||
outputAudioDeviceInfo,
|
||||
audioInputForGUI,
|
||||
audioOutputForGUI,
|
||||
audioMonitorForGUI,
|
||||
fileInputEchoback,
|
||||
shareScreenEnabled,
|
||||
audioOutputForAnalyzer,
|
||||
setInputAudioDeviceInfo,
|
||||
setOutputAudioDeviceInfo,
|
||||
setAudioInputForGUI,
|
||||
setAudioOutputForGUI,
|
||||
setAudioMonitorForGUI,
|
||||
setFileInputEchoback,
|
||||
setShareScreenEnabled,
|
||||
setAudioOutputForAnalyzer,
|
||||
|
||||
modelSlotNum,
|
||||
setModelSlotNum,
|
||||
|
||||
textInputResolve,
|
||||
setTextInputResolve,
|
||||
|
||||
// For Beatrice
|
||||
beatriceJVSSpeakerId,
|
||||
beatriceJVSSpeakerPitch,
|
||||
setBeatriceJVSSpeakerId,
|
||||
setBeatriceJVSSpeakerPitch,
|
||||
};
|
||||
return <GuiStateContext.Provider value={providerValue}>{children}</GuiStateContext.Provider>;
|
||||
};
|