Delete system directory
No files matched your search
|
Before Width: | Height: | Size: 440 KiB |
|
Before Width: | Height: | Size: 25 KiB |
@@ -1,260 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>AllTalk Startup Settings</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
margin: 5px;
|
||||
padding: 5px;
|
||||
background-color: #f4f4f4;
|
||||
}
|
||||
|
||||
h1 {
|
||||
color: #333;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3 {
|
||||
text-decoration: underline;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
form {
|
||||
max-width: 975px;
|
||||
margin: 0 auto;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
gap: 5px;
|
||||
/* Adjusted the gap to create more space */
|
||||
justify-content: start;
|
||||
}
|
||||
|
||||
.radio-group {
|
||||
grid-column: span 2;
|
||||
/* Span both columns */
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
label {
|
||||
display: block;
|
||||
margin-top: 2px;
|
||||
color: #555;
|
||||
}
|
||||
|
||||
select,
|
||||
input,
|
||||
button {
|
||||
width: 100%;
|
||||
padding: 3px;
|
||||
margin-top: 1px;
|
||||
margin-bottom: 3px;
|
||||
box-sizing: border-box;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
button {
|
||||
background-color: #4caf50;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 5px;
|
||||
cursor: pointer;
|
||||
font-size: 12px;
|
||||
grid-column: span 4;
|
||||
}
|
||||
|
||||
.warning {
|
||||
grid-column: span 4;
|
||||
/* Span all 4 columns */
|
||||
text-align: center;
|
||||
/* Center-align the text */
|
||||
color: red;
|
||||
/* Adjusted color for emphasis */
|
||||
font-weight: bold;
|
||||
/* Make the text bold */
|
||||
margin-top: 10px;
|
||||
/* Add some space between the button and the warning */
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h3>AllTalk Startup Settings</h3><br>
|
||||
<form action="/update-settings" method="post">
|
||||
|
||||
<label for="activate" style="color: #b273fa;">TG-webui Activate TTS:</label>
|
||||
<select id="activate" name="activate" required="">
|
||||
<option {% if data.activate %}selected{% endif %} value="true">True</option>
|
||||
<option {% if not data.activate %}selected{% endif %} value="false">False</option>
|
||||
</select>
|
||||
|
||||
<label for="autoplay" style="color: #b273fa;"> TG-webui Autoplay TTS:</label>
|
||||
<select id="autoplay" name="autoplay" required="">
|
||||
<option {% if data.autoplay %}selected{% endif %} value="true">True</option>
|
||||
<option {% if not data.autoplay %}selected{% endif %} value="false">False</option>
|
||||
</select>
|
||||
|
||||
<label for="show_text" style="color: #b273fa;">TG-webui Show Text:</label>
|
||||
<select id="show_text" name="show_text" required="">
|
||||
<option {% if data.show_text %}selected{% endif %} value="true">True</option>
|
||||
<option {% if not data.show_text %}selected{% endif %} value="false">False</option>
|
||||
</select>
|
||||
|
||||
<label for="voice" style="color: #b273fa;"> TG-webui Default voice:</label>
|
||||
<select id="voice" name="voice" required="">
|
||||
{% for file in wav_files %}
|
||||
<option value="{{ file }}" {% if data.voice==file %}selected{% endif %}>{{ file }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
|
||||
|
||||
<label for="language" style="color: #b273fa;">TG-webui Default Language:</label>
|
||||
<select id="language" name="language" required="">
|
||||
<option value="Arabic" {% if data.language=='Arabic' %}selected{% endif %}>Arabic</option>
|
||||
<option value="Chinese" {% if data.language=='Chinese' %}selected{% endif %}>Chinese</option>
|
||||
<option value="Czech" {% if data.language=='Czech' %}selected{% endif %}>Czech</option>
|
||||
<option value="Dutch" {% if data.language=='Dutch' %}selected{% endif %}>Dutch</option>
|
||||
<option value="English" {% if data.language=='English' %}selected{% endif %}>English</option>
|
||||
<option value="French" {% if data.language=='French' %}selected{% endif %}>French</option>
|
||||
<option value="German" {% if data.language=='German' %}selected{% endif %}>German</option>
|
||||
<option value="Hungarian" {% if data.language=='Hungarian' %}selected{% endif %}>Hungarian</option>
|
||||
<option value="Italian" {% if data.language=='Italian' %}selected{% endif %}>Italian</option>
|
||||
<option value="Japanese" {% if data.language=='Japanese' %}selected{% endif %}>Japanese</option>
|
||||
<option value="Korean" {% if data.language=='Korean' %}selected{% endif %}>Korean</option>
|
||||
<option value="Polish" {% if data.language=='Polish' %}selected{% endif %}>Polish</option>
|
||||
<option value="Portuguese" {% if data.language=='Portuguese' %}selected{% endif %}>Portuguese</option>
|
||||
<option value="Russian" {% if data.language=='Russian' %}selected{% endif %}>Russian</option>
|
||||
<option value="Spanish" {% if data.language=='Spanish' %}selected{% endif %}>Spanish</option>
|
||||
<option value="Turkish" {% if data.language=='Turkish' %}selected{% endif %}>Turkish</option>
|
||||
</select>
|
||||
|
||||
<label for="narrator_voice" style="color: #b273fa;"> TG-webui Narrator voice:</label>
|
||||
<select id="narrator_voice" name="narrator_voice" required="">
|
||||
{% for file in wav_files %}
|
||||
<option value="{{ file }}" {% if data.narrator_voice==file %}selected{% endif %}>{{ file }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
|
||||
<label for="remove_trailing_dots" style="color: #b273fa;">TG-webui Remove Trailing Dots:</label>
|
||||
<select id="remove_trailing_dots" name="remove_trailing_dots" required="">
|
||||
<option {% if data.remove_trailing_dots %}selected{% endif %} value="true">True</option>
|
||||
<option {% if not data.remove_trailing_dots %}selected{% endif %} value="false">False</option>
|
||||
</select>
|
||||
|
||||
<label for="narrator_enabled" style="color: #b273fa;"> TG-webui Narrator enabled:</label>
|
||||
<select id="narrator_enabled" name="narrator_enabled" required="">
|
||||
<option {% if data.narrator_enabled %}selected{% endif %} value="true">True</option>
|
||||
<option {% if not data.narrator_enabled %}selected{% endif %} value="false">False</option>
|
||||
</select>
|
||||
|
||||
<label for="delete_output_wavs" style="color: #33cc33;">Del WAV's older than:</label>
|
||||
<select id="delete_output_wavs" name="delete_output_wavs" required="">
|
||||
<option value="Disabled" {% if data.delete_output_wavs=='Disabled' %}selected{% endif %}>Disabled</option>
|
||||
<option value="1 Day" {% if data.delete_output_wavs=='1 Day' %}selected{% endif %}>1 Day</option>
|
||||
<option value="2 Days" {% if data.delete_output_wavs=='2 Days' %}selected{% endif %}>2 Days</option>
|
||||
<option value="3 Days" {% if data.delete_output_wavs=='3 Days' %}selected{% endif %}>3 Days</option>
|
||||
<option value="4 Day" {% if data.delete_output_wavs=='4 Days' %}selected{% endif %}>4 Days</option>
|
||||
<option value="5 Day" {% if data.delete_output_wavs=='5 Days' %}selected{% endif %}>5 Days</option>
|
||||
<option value="6 Day" {% if data.delete_output_wavs=='6 Days' %}selected{% endif %}>6 Days</option>
|
||||
<option value="7 Days" {% if data.delete_output_wavs=='7 Days' %}selected{% endif %}>7 Days</option>
|
||||
<option value="14 Days" {% if data.delete_output_wavs=='14 Days' %}selected{% endif %}>14 Days</option>
|
||||
<option value="21 Days" {% if data.delete_output_wavs=='21 Days' %}selected{% endif %}>21 Days</option>
|
||||
<option value="28 Days" {% if data.delete_output_wavs=='28 Days' %}selected{% endif %}>28 Days</option>
|
||||
</select>
|
||||
|
||||
|
||||
<label for="low_vram" style="color: #33cc33;"> Low VRAM:</label>
|
||||
<select id="low_vram" name="low_vram" required="">
|
||||
<option {% if data.low_vram %}selected{% endif %} value="true">True</option>
|
||||
<option {% if not data.low_vram %}selected{% endif %} value="false">False</option>
|
||||
</select>
|
||||
|
||||
<label for="local_temperature" style="color: red;">Local Model temperature:</label>
|
||||
<select id="local_temperature" name="local_temperature" required="">
|
||||
{% for temp in range(0, 101, 5) %}
|
||||
<option value="{{ temp/100 }}" {% if data.local_temperature|float == temp/100 %}selected{% endif %}>{{ "{:.2f}".format(temp/100) }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
|
||||
<label for="local_repetition_penalty" style="color: red;"> Local Model repetition penalty:</label>
|
||||
<select id="local_repetition_penalty" name="local_repetition_penalty" required="">
|
||||
{% for repetition in range(10, 210, 10) %}
|
||||
<option value="{{ repetition/10 }}" {% if data.local_repetition_penalty|float == repetition/10 %}selected{% endif %}>{{ repetition/10 }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
|
||||
<label for="deepspeed_activate" style="color: red;">DeepSpeed Activate:</label>
|
||||
<select id="deepspeed_activate" name="deepspeed_activate" required="">
|
||||
<option {% if data.deepspeed_activate %}selected{% endif %} value="true">True</option>
|
||||
<option {% if not data.deepspeed_activate %}selected{% endif %} value="false">False</option>
|
||||
</select>
|
||||
|
||||
<label for="output_folder_wav" style="color: red;"> WAV Output Folder:</label>
|
||||
<input id="output_folder_wav" name="output_folder_wav" required="" type="text"
|
||||
value="{{ data.output_folder_wav }}" />
|
||||
|
||||
|
||||
<input type="hidden" id="tts_model_loaded" name="tts_model_loaded" value="{{ data.tts_model_loaded }}" />
|
||||
|
||||
<!-- Continue updating other dropdowns and inputs in a similar manner -->
|
||||
|
||||
<label for="tts_model_name" style="color: red;"> API TTS Model Name:</label>
|
||||
<input id="tts_model_name" name="tts_model_name" required="" type="text" value="{{ data.tts_model_name }}" />
|
||||
|
||||
<label for="model_version"
|
||||
style="color: red; font-size: 16px; line-height: 1; vertical-align: bottom; margin-bottom: 0;">
|
||||
API Local Model Folder:</label>
|
||||
<span style="font-size: 14px; vertical-align: bottom; margin-bottom: 0; margin-top: 2px;">{{
|
||||
modeldownload_model_path }}</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<label for="ip_address" style="color: red;"> IP Address:</label>
|
||||
<input id="ip_address" name="ip_address" required="" type="text" value="{{ data.ip_address }}" />
|
||||
|
||||
<label for="port_number" style="color: red;"> Port Number:</label>
|
||||
<input id="port_number" name="port_number" required="" type="text" value="{{ data.port_number }}" />
|
||||
|
||||
<div class="radio-group">
|
||||
<label for="tts_method_api_local" style="color: #33cc33;">Model: <span
|
||||
style="color: black; font-weight: normal;">API Local</span>:</label>
|
||||
<input id="tts_method_api_local_true" {% if data.tts_method_api_local %}checked{% endif %} name="tts_method"
|
||||
type="radio" value="api_local" />
|
||||
</div>
|
||||
|
||||
<div class="radio-group">
|
||||
<label for="tts_method_api_tts" style="color: #33cc33;"> Model: <span
|
||||
style="color: black; font-weight: normal;">API TTS</span>:</label>
|
||||
<input id="tts_method_api_tts_true" {% if data.tts_method_api_tts %}checked{% endif %} name="tts_method"
|
||||
type="radio" value="api_tts" />
|
||||
</div>
|
||||
|
||||
<div class="radio-group">
|
||||
<label for="tts_method_xtts_local" style="color: #33cc33;">Model: <span
|
||||
style="color: black; font-weight: normal;">XTTS Local</span>:</label>
|
||||
<input id="tts_method_xtts_local_true" {% if data.tts_method_xtts_local %}checked{% endif %}
|
||||
name="tts_method" type="radio" value="xtts_local" />
|
||||
</div>
|
||||
<button type="submit">Update Settings</button>
|
||||
</form>
|
||||
<p class="warning">WARNING: Changing RED items or setting DeepSpeed to True on a system without DeepSpeed installed,
|
||||
may cause errors.</p>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
Before Width: | Height: | Size: 445 KiB |
|
Before Width: | Height: | Size: 476 KiB |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 547 KiB |
|
Before Width: | Height: | Size: 171 KiB |
|
Before Width: | Height: | Size: 172 KiB |
|
Before Width: | Height: | Size: 156 KiB |
@@ -1,2 +0,0 @@
|
||||
{
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
{
|
||||
}
|
||||
@@ -1,720 +0,0 @@
|
||||
The birch canoe slid on the smooth planks.
|
||||
Glue the sheet to the dark blue background.
|
||||
It's easy to tell the depth of a well.
|
||||
These days a chicken leg is a rare dish.
|
||||
Rice is often served in round bowls.
|
||||
The juice of lemons makes fine punch.
|
||||
The box was thrown beside the parked truck.
|
||||
The hogs were fed chopped corn and garbage.
|
||||
Four hours of steady work faced us.
|
||||
A large size in stockings is hard to sell.
|
||||
The boy was there when the sun rose.
|
||||
A rod is used to catch pink salmon.
|
||||
The source of the huge river is the clear spring.
|
||||
Kick the ball straight and follow through.
|
||||
Help the woman get back to her feet.
|
||||
A pot of tea helps to pass the evening.
|
||||
Smoky fires lack flame and heat.
|
||||
The soft cushion broke the man's fall.
|
||||
The salt breeze came across from the sea.
|
||||
The girl at the booth sold fifty bonds.
|
||||
The small pup gnawed a hole in the sock.
|
||||
The fish twisted and turned on the bent hook.
|
||||
Press the pants and sew a button on the vest.
|
||||
The swan dive was far short of perfect.
|
||||
The beauty of the view stunned the young boy.
|
||||
Two blue fish swam in the tank.
|
||||
Her purse was full of useless trash.
|
||||
The colt reared and threw the tall rider.
|
||||
It snowed, rained, and hailed the same morning.
|
||||
Read verse out loud for pleasure.
|
||||
Hoist the load to your left shoulder.
|
||||
Take the winding path to reach the lake.
|
||||
Note closely the size of the gas tank.
|
||||
Wipe the grease off his dirty face.
|
||||
Mend the coat before you go out.
|
||||
The wrist was badly strained and hung limp.
|
||||
The stray cat gave birth to kittens.
|
||||
The young girl gave no clear response.
|
||||
The meal was cooked before the bell rang.
|
||||
What joy there is in living.
|
||||
A king ruled the state in the early days.
|
||||
The ship was torn apart on the sharp reef.
|
||||
Sickness kept him home the third week.
|
||||
The wide road shimmered in the hot sun.
|
||||
The lazy cow lay in the cool grass.
|
||||
Lift the square stone over the fence.
|
||||
The rope will bind the seven books at once.
|
||||
Hop over the fence and plunge in.
|
||||
The friendly gang left the drug store.
|
||||
Mesh wire keeps chicks inside.
|
||||
The frosty air passed through the coat.
|
||||
The crooked maze failed to fool the mouse.
|
||||
Adding fast leads to wrong sums.
|
||||
The show was a flop from the very start.
|
||||
A saw is a tool used for making boards.
|
||||
The wagon moved on well oiled wheels.
|
||||
March the soldiers past the next hill.
|
||||
A cup of sugar makes sweet fudge.
|
||||
Place a rosebush near the porch steps.
|
||||
Both lost their lives in the raging storm.
|
||||
We talked of the side show in the circus.
|
||||
Use a pencil to write the first draft.
|
||||
He ran half way to the hardware store.
|
||||
The clock struck to mark the third period.
|
||||
A small creek cut across the field.
|
||||
Cars and busses stalled in snow drifts.
|
||||
The set of china hit the floor with a crash.
|
||||
This is a grand season for hikes on the road.
|
||||
The dune rose from the edge of the water.
|
||||
Those words were the cue for the actor to leave.
|
||||
A yacht slid around the point into the bay.
|
||||
The two met while playing on the sand.
|
||||
The ink stain dried on the finished page.
|
||||
The walled town was seized without a fight.
|
||||
The lease ran out in sixteen weeks.
|
||||
A tame squirrel makes a nice pet.
|
||||
The horn of the car woke the sleeping cop.
|
||||
The heart beat strongly and with firm strokes.
|
||||
The pearl was worn in a thin silver ring.
|
||||
The fruit peel was cut in thick slices.
|
||||
The Navy attacked the big task force.
|
||||
See the cat glaring at the scared mouse.
|
||||
There are more than two factors here.
|
||||
The hat brim was wide and too droopy.
|
||||
The lawyer tried to lose his case.
|
||||
The grass curled around the fence post.
|
||||
Cut the pie into large parts.
|
||||
Men strive but seldom get rich.
|
||||
Always close the barn door tight.
|
||||
He lay prone and hardly moved a limb.
|
||||
The slush lay deep along the street.
|
||||
A wisp of cloud hung in the blue air.
|
||||
A pound of sugar costs more than eggs.
|
||||
The fin was sharp and cut the clear water.
|
||||
The play seems dull and quite stupid.
|
||||
Bail the boat to stop it from sinking.
|
||||
The term ended in late June that year.
|
||||
A tusk is used to make costly gifts.
|
||||
Ten pins were set in order.
|
||||
The bill was paid every third week.
|
||||
Oak is strong and also gives shade.
|
||||
Cats and dogs each hate the other.
|
||||
The pipe began to rust while new.
|
||||
Open the crate but don't break the glass.
|
||||
Add the sum to the product of these three.
|
||||
Thieves who rob friends deserve jail.
|
||||
The ripe taste of cheese improves with age.
|
||||
Act on these orders with great speed.
|
||||
The hog crawled under the high fence.
|
||||
Move the vat over the hot fire.
|
||||
The bark of the pine tree was shiny and dark.
|
||||
Leaves turn brown and yellow in the fall.
|
||||
The pennant waved when the wind blew.
|
||||
Split the log with a quick, sharp blow.
|
||||
Burn peat after the logs give out.
|
||||
He ordered peach pie with ice cream.
|
||||
Weave the carpet on the right hand side.
|
||||
Hemp is a weed found in parts of the tropics.
|
||||
A lame back kept his score low.
|
||||
We find joy in the simplest things.
|
||||
Type out three lists of orders.
|
||||
The harder he tried the less he got done.
|
||||
The boss ran the show with a watchful eye.
|
||||
The cup cracked and spilled its contents.
|
||||
Paste can cleanse the most dirty brass.
|
||||
The slang word for raw whiskey is booze.
|
||||
It caught its hind paw in a rusty trap.
|
||||
The wharf could be seen at the farther shore.
|
||||
Feel the heat of the weak dying flame.
|
||||
The tiny girl took off her hat.
|
||||
A cramp is no small danger on a swim.
|
||||
He said the same phrase thirty times.
|
||||
Pluck the bright rose without leaves.
|
||||
Two plus seven is less than ten.
|
||||
The glow deepened in the eyes of the sweet girl.
|
||||
Bring your problems to the wise chief.
|
||||
Write a fond note to the friend you cherish.
|
||||
Clothes and lodging are free to new men.
|
||||
We frown when events take a bad turn.
|
||||
Port is a strong wine with a smoky taste.
|
||||
The young kid jumped the rusty gate.
|
||||
Guess the results from the first scores.
|
||||
A salt pickle tastes fine with ham.
|
||||
The just claim got the right verdict.
|
||||
These thistles bend in a high wind.
|
||||
Pure bred poodles have curls.
|
||||
The tree top waved in a graceful way.
|
||||
The spot on the blotter was made by green ink.
|
||||
Mud was spattered on the front of his white shirt.
|
||||
The cigar burned a hole in the desk top.
|
||||
The empty flask stood on the tin tray.
|
||||
A speedy man can beat this track mark.
|
||||
He broke a new shoelace that day.
|
||||
The coffee stand is too high for the couch.
|
||||
The urge to write short stories is rare.
|
||||
The pencils have all been used.
|
||||
The pirates seized the crew of the lost ship.
|
||||
We tried to replace the coin but failed.
|
||||
She sewed the torn coat quite neatly.
|
||||
The sofa cushion is red and of light weight.
|
||||
The jacket hung on the back of the wide chair.
|
||||
At that high level the air is pure.
|
||||
Drop the two when you add the figures.
|
||||
A filing case is now hard to buy.
|
||||
An abrupt start does not win the prize.
|
||||
Wood is best for making toys and blocks.
|
||||
The office paint was a dull, sad tan.
|
||||
He knew the skill of the great young actress.
|
||||
A rag will soak up spilled water.
|
||||
A shower of dirt fell from the hot pipes.
|
||||
Steam hissed from the broken valve.
|
||||
The child almost hurt the small dog.
|
||||
There was a sound of dry leaves outside.
|
||||
The sky that morning was clear and bright blue.
|
||||
Torn scraps littered the stone floor.
|
||||
Sunday is the best part of the week.
|
||||
The doctor cured him with these pills.
|
||||
The new girl was fired today at noon.
|
||||
They felt gay when the ship arrived in port.
|
||||
Add the store's account to the last cent.
|
||||
Acid burns holes in wool cloth.
|
||||
Fairy tales should be fun to write.
|
||||
Eight miles of woodland burned to waste.
|
||||
The third act was dull and tired the players.
|
||||
A young child should not suffer fright.
|
||||
Add the column and put the sum here.
|
||||
We admire and love a good cook.
|
||||
There the flood mark is ten inches.
|
||||
He carved a head from the round block of marble.
|
||||
She has a smart way of wearing clothes.
|
||||
The fruit of a fig tree is apple-shaped.
|
||||
Corn cobs can be used to kindle a fire.
|
||||
Where were they when the noise started.
|
||||
The paper box is full of thumb tacks.
|
||||
Sell your gift to a buyer at a good gain.
|
||||
The tongs lay beside the ice pail.
|
||||
The petals fall with the next puff of wind.
|
||||
Bring your best compass to the third class.
|
||||
They could laugh although they were sad.
|
||||
Farmers came in to thresh the oat crop.
|
||||
The brown house was on fire to the attic.
|
||||
The lure is used to catch trout and flounder.
|
||||
Float the soap on top of the bath water.
|
||||
A blue crane is a tall wading bird.
|
||||
A fresh start will work such wonders.
|
||||
The club rented the rink for the fifth night.
|
||||
After the dance, they went straight home.
|
||||
The hostess taught the new maid to serve.
|
||||
He wrote his last novel there at the inn.
|
||||
Even the worst will beat his low score.
|
||||
The cement had dried when he moved it.
|
||||
The loss of the second ship was hard to take.
|
||||
The fly made its way along the wall.
|
||||
Do that with a wooden stick.
|
||||
Live wires should be kept covered.
|
||||
The large house had hot water taps.
|
||||
It is hard to erase blue or red ink.
|
||||
Write at once or you may forget it.
|
||||
The doorknob was made of bright clean brass.
|
||||
The wreck occurred by the bank on Main Street.
|
||||
A pencil with black lead writes best.
|
||||
Coax a young calf to drink from a bucket.
|
||||
Schools for ladies teach charm and grace.
|
||||
The lamp shone with a steady green flame.
|
||||
They took the axe and the saw to the forest.
|
||||
The ancient coin was quite dull and worn.
|
||||
The shaky barn fell with a loud crash.
|
||||
Jazz and swing fans like fast music.
|
||||
Rake the rubbish up and then burn it.
|
||||
Slash the gold cloth into fine ribbons.
|
||||
Try to have the court decide the case.
|
||||
They are pushed back each time they attack.
|
||||
He broke his ties with groups of former friends.
|
||||
They floated on the raft to sun their white backs.
|
||||
The map had an X that meant nothing.
|
||||
Whitings are small fish caught in nets.
|
||||
Some ads serve to cheat buyers.
|
||||
Jerk the rope and the bell rings weakly.
|
||||
A waxed floor makes us lose balance.
|
||||
Madam, this is the best brand of corn.
|
||||
On the islands the sea breeze is soft and mild.
|
||||
The play began as soon as we sat down.
|
||||
This will lead the world to more sound and fury.
|
||||
Add salt before you fry the egg.
|
||||
The rush for funds reached its peak Tuesday.
|
||||
The birch looked stark white and lonesome.
|
||||
The box is held by a bright red snapper.
|
||||
To make pure ice, you freeze water.
|
||||
The first worm gets snapped early.
|
||||
Jump the fence and hurry up the bank.
|
||||
Yell and clap as the curtain slides back.
|
||||
They are men who walk the middle of the road.
|
||||
Both brothers wear the same size.
|
||||
In some form or other we need fun.
|
||||
The prince ordered his head chopped off.
|
||||
The houses are built of red clay bricks.
|
||||
Ducks fly north but lack a compass.
|
||||
Fruit flavors are used in fizz drinks.
|
||||
These pills do less good than others.
|
||||
Canned pears lack full flavor.
|
||||
The dark pot hung in the front closet.
|
||||
Carry the pail to the wall and spill it there.
|
||||
The train brought our hero to the big town.
|
||||
We are sure that one war is enough.
|
||||
Gray paint stretched for miles around.
|
||||
The rude laugh filled the empty room.
|
||||
High seats are best for football fans.
|
||||
Tea served from the brown jug is tasty.
|
||||
A dash of pepper spoils beef stew.
|
||||
A zestful food is the hot-cross bun.
|
||||
The horse trotted around the field at a brisk pace.
|
||||
Find the twin who stole the pearl necklace.
|
||||
Cut the cord that binds the box tightly.
|
||||
The red tape bound the smuggled food.
|
||||
Look in the corner to find the tan shirt.
|
||||
The cold drizzle will halt the bond drive.
|
||||
Nine men were hired to dig the ruins.
|
||||
The junk yard had a mouldy smell.
|
||||
The flint sputtered and lit a pine torch.
|
||||
Soak the cloth and drown the sharp odor.
|
||||
The shelves were bare of both jam or crackers.
|
||||
A joy to every child is the swan boat.
|
||||
All sat frozen and watched the screen.
|
||||
A cloud of dust stung his tender eyes.
|
||||
To reach the end he needs much courage.
|
||||
Shape the clay gently into block form.
|
||||
A ridge on a smooth surface is a bump or flaw.
|
||||
Hedge apples may stain your hands green.
|
||||
Quench your thirst, then eat the crackers.
|
||||
Tight curls get limp on rainy days.
|
||||
The mute muffled the high tones of the horn.
|
||||
The gold ring fits only a pierced ear.
|
||||
The old pan was covered with hard fudge.
|
||||
Watch the log float in the wide river.
|
||||
The node on the stalk of wheat grew daily.
|
||||
The heap of fallen leaves was set on fire.
|
||||
Write fast if you want to finish early.
|
||||
His shirt was clean but one button was gone.
|
||||
The barrel of beer was a brew of malt and hops.
|
||||
Tin cans are absent from store shelves.
|
||||
Slide the box into that empty space.
|
||||
The plant grew large and green in the window.
|
||||
The beam dropped down on the workmen's head.
|
||||
Pink clouds floated with the breeze.
|
||||
She danced like a swan, tall and graceful.
|
||||
The tube was blown and the tire flat and useless.
|
||||
It is late morning on the old wall clock.
|
||||
Let's all join as we sing the last chorus.
|
||||
The last switch cannot be turned off.
|
||||
The fight will end in just six minutes.
|
||||
The store walls were lined with colored frocks.
|
||||
The peace league met to discuss their plans.
|
||||
The rise to fame of a person takes luck.
|
||||
Paper is scarce, so write with much care.
|
||||
The quick fox jumped on the sleeping cat.
|
||||
The nozzle of the fire hose was bright brass.
|
||||
Screw the round cap on as tight as needed.
|
||||
Time brings us many changes.
|
||||
The purple tie was ten years old.
|
||||
Men think and plan and sometimes act.
|
||||
Fill the ink jar with sticky glue.
|
||||
He smoke a big pipe with strong contents.
|
||||
We need grain to keep our mules healthy.
|
||||
Pack the records in a neat thin case.
|
||||
The crunch of feet in the snow was the only sound.
|
||||
The copper bowl shone in the sun's rays.
|
||||
Boards will warp unless kept dry.
|
||||
The plush chair leaned against the wall.
|
||||
Glass will clink when struck by metal.
|
||||
Bathe and relax in the cool green grass.
|
||||
Nine rows of soldiers stood in line.
|
||||
The beach is dry and shallow at low tide.
|
||||
The idea is to sew both edges straight.
|
||||
The kitten chased the dog down the street.
|
||||
Pages bound in cloth make a book.
|
||||
Try to trace the fine lines of the painting.
|
||||
Women form less than half of the group.
|
||||
The zones merge in the central part of town.
|
||||
A gem in the rough needs work to polish.
|
||||
Code is used when secrets are sent.
|
||||
Most of the news is easy for us to hear.
|
||||
He used the lathe to make brass objects.
|
||||
The vane on top of the pole revolved in the wind.
|
||||
Mince pie is a dish served to children.
|
||||
The clan gathered on each dull night.
|
||||
Let it burn, it gives us warmth and comfort.
|
||||
A castle built from sand fails to endure.
|
||||
A child's wit saved the day for us.
|
||||
Tack the strip of carpet to the worn floor.
|
||||
Next Tuesday we must vote.
|
||||
Pour the stew from the pot into the plate.
|
||||
Each penny shone like new.
|
||||
The man went to the woods to gather sticks.
|
||||
The dirt piles were lines along the road.
|
||||
The logs fell and tumbled into the clear stream.
|
||||
Just hoist it up and take it away.
|
||||
A ripe plum is fit for a king's palate.
|
||||
Our plans right now are hazy.
|
||||
Brass rings are sold by these natives.
|
||||
It takes a good trap to capture a bear.
|
||||
Feed the white mouse some flower seeds.
|
||||
The thaw came early and freed the stream.
|
||||
He took the lead and kept it the whole distance.
|
||||
The key you designed will fit the lock.
|
||||
Plead to the council to free the poor thief.
|
||||
Better hash is made of rare beef.
|
||||
This plank was made for walking on.
|
||||
The lake sparkled in the red hot sun.
|
||||
He crawled with care along the ledge.
|
||||
Tend the sheep while the dog wanders.
|
||||
It takes a lot of help to finish these.
|
||||
Mark the spot with a sign painted red.
|
||||
Take two shares as a fair profit.
|
||||
The fur of cats goes by many names.
|
||||
North winds bring colds and fevers.
|
||||
He asks no person to vouch for him.
|
||||
Go now and come here later.
|
||||
A sash of gold silk will trim her dress.
|
||||
Soap can wash most dirt away.
|
||||
That move means the game is over.
|
||||
He wrote down a long list of items.
|
||||
A siege will crack the strong defense.
|
||||
Grape juice and water mix well.
|
||||
Roads are paved with sticky tar.
|
||||
Fake stones shine but cost little.
|
||||
The drip of the rain made a pleasant sound.
|
||||
Smoke poured out of every crack.
|
||||
Serve the hot rum to the tired heroes.
|
||||
Much of the story makes good sense.
|
||||
The sun came up to light the eastern sky.
|
||||
Heave the line over the port side.
|
||||
A lathe cuts and trims any wood.
|
||||
It's a dense crowd in two distinct ways.
|
||||
His hip struck the knee of the next player.
|
||||
The stale smell of old beer lingers.
|
||||
The desk was firm on the shaky floor.
|
||||
It takes heat to bring out the odor.
|
||||
Beef is scarcer than some lamb.
|
||||
Raise the sail and steer the ship northward.
|
||||
A cone costs five cents on Mondays.
|
||||
A pod is what peas always grow in.
|
||||
Jerk the dart from the cork target.
|
||||
No cement will hold hard wood.
|
||||
We now have a new base for shipping.
|
||||
A list of names is carved around the base.
|
||||
The sheep were led home by a dog.
|
||||
Three for a dime, the young peddler cried.
|
||||
The sense of smell is better than that of touch.
|
||||
No hardship seemed to keep him sad.
|
||||
Grace makes up for lack of beauty.
|
||||
Nudge gently but wake her now.
|
||||
The news struck doubt into restless minds.
|
||||
Once we stood beside the shore.
|
||||
A chink in the wall allowed a draft to blow.
|
||||
Fasten two pins on each side.
|
||||
A cold dip restores health and zest.
|
||||
He takes the oath of office each March.
|
||||
The sand drifts over the sill of the old house.
|
||||
The point of the steel pen was bent and twisted.
|
||||
There is a lag between thought and act.
|
||||
Seed is needed to plant the spring corn.
|
||||
Draw the chart with heavy black lines.
|
||||
The boy owed his pal thirty cents.
|
||||
The chap slipped into the crowd and was lost.
|
||||
Hats are worn to tea and not to dinner.
|
||||
The ramp led up to the wide highway.
|
||||
Beat the dust from the rug onto the lawn.
|
||||
Say it slowly but make it ring clear.
|
||||
The straw nest housed five robins.
|
||||
Screen the porch with woven straw mats.
|
||||
This horse will nose his way to the finish.
|
||||
The dry wax protects the deep scratch.
|
||||
He picked up the dice for a second roll.
|
||||
These coins will be needed to pay his debt.
|
||||
The nag pulled the frail cart along.
|
||||
Twist the valve and release hot steam.
|
||||
The vamp of the shoe had a gold buckle.
|
||||
The smell of burned rags itches my nose.
|
||||
New pants lack cuffs and pockets.
|
||||
The marsh will freeze when cold enough.
|
||||
They slice the sausage thin with a knife.
|
||||
The bloom of the rose lasts a few days.
|
||||
A gray mare walked before the colt.
|
||||
Breakfast buns are fine with a hot drink.
|
||||
Bottles hold four kinds of rum.
|
||||
The man wore a feather in his felt hat.
|
||||
He wheeled the bike past the winding road.
|
||||
Drop the ashes on the worn old rug.
|
||||
The desk and both chairs were painted tan.
|
||||
Throw out the used paper cup and plate.
|
||||
A clean neck means a neat collar.
|
||||
The couch cover and hall drapes were blue.
|
||||
The stems of the tall glasses cracked and broke.
|
||||
The wall phone rang loud and often.
|
||||
The clothes dried on a thin wooden rack.
|
||||
Turn on the lantern which gives us light.
|
||||
The cleat sank deeply into the soft turf.
|
||||
The bills were mailed promptly on the tenth of the month.
|
||||
To have is better than to wait and hope.
|
||||
The price is fair for a good antique clock.
|
||||
The music played on while they talked.
|
||||
Dispense with a vest on a day like this.
|
||||
The bunch of grapes was pressed into wine.
|
||||
He sent the figs, but kept the ripe cherries.
|
||||
The hinge on the door creaked with old age.
|
||||
The screen before the fire kept in the sparks.
|
||||
Fly by night, and you waste little time.
|
||||
Thick glasses helped him read the print.
|
||||
Birth and death mark the limits of life.
|
||||
The chair looked strong but had no bottom.
|
||||
The kite flew wildly in the high wind.
|
||||
A fur muff is stylish once more.
|
||||
The tin box held priceless stones.
|
||||
We need an end of all such matter.
|
||||
The case was puzzling to the old and wise.
|
||||
The bright lanterns were gay on the dark lawn.
|
||||
We don't get much money but we have fun.
|
||||
The youth drove with zest, but little skill.
|
||||
Five years he lived with a shaggy dog.
|
||||
A fence cuts through the corner lot.
|
||||
The way to save money is not to spend much.
|
||||
Shut the hatch before the waves push it in.
|
||||
The odor of spring makes young hearts jump.
|
||||
Crack the walnut with your sharp side teeth.
|
||||
He offered proof in the form of a large chart.
|
||||
Send the stuff in a thick paper bag.
|
||||
A quart of milk is water for the most part.
|
||||
They told wild tales to frighten him.
|
||||
The three story house was built of stone.
|
||||
In the rear of the ground floor was a large passage.
|
||||
A man in a blue sweater sat at the desk.
|
||||
Oats are a food eaten by horse and man.
|
||||
Their eyelids droop for want of sleep.
|
||||
A sip of tea revives his tired friend.
|
||||
There are many ways to do these things.
|
||||
Tuck the sheet under the edge of the mat.
|
||||
A force equal to that would move the earth.
|
||||
We like to see clear weather.
|
||||
The work of the tailor is seen on each side.
|
||||
Take a chance and win a china doll.
|
||||
Shake the dust from your shoes, stranger.
|
||||
She was kind to sick old people.
|
||||
The square wooden crate was packed to be shipped.
|
||||
The dusty bench stood by the stone wall.
|
||||
We dress to suit the weather of most days.
|
||||
Smile when you say nasty words.
|
||||
A bowl of rice is free with chicken stew.
|
||||
The water in this well is a source of good health.
|
||||
Take shelter in this tent, but keep still.
|
||||
That guy is the writer of a few banned books.
|
||||
The little tales they tell are false.
|
||||
The door was barred, locked, and bolted as well.
|
||||
Ripe pears are fit for a queen's table.
|
||||
A big wet stain was on the round carpet.
|
||||
The kite dipped and swayed, but stayed aloft.
|
||||
The pleasant hours fly by much too soon.
|
||||
The room was crowded with a wild mob.
|
||||
This strong arm shall shield your honor.
|
||||
She blushed when he gave her a white orchid.
|
||||
The beetle droned in the hot June sun.
|
||||
Press the pedal with your left foot.
|
||||
Neat plans fail without luck.
|
||||
The black trunk fell from the landing.
|
||||
The bank pressed for payment of the debt.
|
||||
The theft of the pearl pin was kept secret.
|
||||
Shake hands with this friendly child.
|
||||
The vast space stretched into the far distance.
|
||||
A rich farm is rare in this sandy waste.
|
||||
His wide grin earned many friends.
|
||||
Flax makes a fine brand of paper.
|
||||
Hurdle the pit with the aid of a long pole.
|
||||
A strong bid may scare your partner stiff.
|
||||
Even a just cause needs power to win.
|
||||
Peep under the tent and see the clowns.
|
||||
The leaf drifts along with a slow spin.
|
||||
Cheap clothes are flashy but don't last.
|
||||
A thing of small note can cause despair.
|
||||
Flood the mails with requests for this book.
|
||||
A thick coat of black paint covered all.
|
||||
The pencil was cut to be sharp at both ends.
|
||||
Those last words were a strong statement.
|
||||
He wrote his name boldly at the top of the sheet.
|
||||
Dill pickles are sour but taste fine.
|
||||
Down that road is the way to the grain farmer.
|
||||
Either mud or dust are found at all times.
|
||||
The best method is to fix it in place with clips.
|
||||
If you mumble your speech will be lost.
|
||||
At night the alarm roused him from a deep sleep.
|
||||
Read just what the meter says.
|
||||
Fill your pack with bright trinkets for the poor.
|
||||
The small red neon lamp went out.
|
||||
Clams are small, round, soft, and tasty.
|
||||
The fan whirled its round blades softly.
|
||||
The line where the edges join was clean.
|
||||
Breathe deep and smell the piny air.
|
||||
It matters not if he reads these words or those.
|
||||
A brown leather bag hung from its strap.
|
||||
A toad and a frog are hard to tell apart.
|
||||
A white silk jacket goes with any shoes.
|
||||
A break in the dam almost caused a flood.
|
||||
Paint the sockets in the wall dull green.
|
||||
The child crawled into the dense grass.
|
||||
Bribes fail where honest men work.
|
||||
Trample the spark, else the flames will spread.
|
||||
The hilt of the sword was carved with fine designs.
|
||||
A round hole was drilled through the thin board.
|
||||
Footprints showed the path he took up the beach.
|
||||
She was waiting at my front lawn.
|
||||
A vent near the edge brought in fresh air.
|
||||
Prod the old mule with a crooked stick.
|
||||
It is a band of steel three inches wide.
|
||||
The pipe ran almost the length of the ditch.
|
||||
It was hidden from sight by a mass of leaves and shrubs.
|
||||
The weight of the package was seen on the high scale.
|
||||
Wake and rise, and step into the green outdoors.
|
||||
The green light in the brown box flickered.
|
||||
The brass tube circled the high wall.
|
||||
The lobes of her ears were pierced to hold rings.
|
||||
Hold the hammer near the end to drive the nail.
|
||||
Next Sunday is the twelfth of the month.
|
||||
Every word and phrase he speaks is true.
|
||||
He put his last cartridge into the gun and fired.
|
||||
They took their kids from the public school.
|
||||
Drive the screw straight into the wood.
|
||||
Keep the hatch tight and the watch constant.
|
||||
Sever the twine with a quick snip of the knife.
|
||||
Paper will dry out when wet.
|
||||
Slide the catch back and open the desk.
|
||||
Help the weak to preserve their strength.
|
||||
A sullen smile gets few friends.
|
||||
Stop whistling and watch the boys march.
|
||||
Jerk the cord, and out tumbles the gold.
|
||||
Slide the tray across the glass top.
|
||||
The cloud moved in a stately way and was gone.
|
||||
Light maple makes for a swell room.
|
||||
Set the piece here and say nothing.
|
||||
Dull stories make her laugh.
|
||||
A stiff cord will do to fasten your shoe.
|
||||
Get the trust fund to the bank early.
|
||||
Choose between the high road and the low.
|
||||
A plea for funds seems to come again.
|
||||
He lent his coat to the tall gaunt stranger.
|
||||
There is a strong chance it will happen once more.
|
||||
The duke left the park in a silver coach.
|
||||
Greet the new guests and leave quickly.
|
||||
When the frost has come it is time for turkey.
|
||||
Sweet words work better than fierce.
|
||||
A thin stripe runs down the middle.
|
||||
A six comes up more often than a ten.
|
||||
Lush fern grow on the lofty rocks.
|
||||
The ram scared the school children off.
|
||||
The team with the best timing looks good.
|
||||
The farmer swapped his horse for a brown ox.
|
||||
Sit on the perch and tell the others what to do.
|
||||
A steep trail is painful for our feet.
|
||||
The early phase of life moves fast.
|
||||
Green moss grows on the northern side.
|
||||
Tea in thin china has a sweet taste.
|
||||
Pitch the straw through the door of the stable.
|
||||
The latch on the back gate needed a nail.
|
||||
The goose was brought straight from the old market.
|
||||
The sink is the thing in which we pile dishes.
|
||||
A whiff of it will cure the most stubborn cold.
|
||||
The facts don't always show who is right.
|
||||
She flaps her cape as she parades the street.
|
||||
The loss of the cruiser was a blow to the fleet.
|
||||
Loop the braid to the left and then over.
|
||||
Plead with the lawyer to drop the lost cause.
|
||||
Calves thrive on tender spring grass.
|
||||
Post no bills on this office wall.
|
||||
Tear a thin sheet from the yellow pad.
|
||||
A cruise in warm waters in a sleek yacht is fun.
|
||||
A streak of color ran down the left edge.
|
||||
It was done before the boy could see it.
|
||||
Crouch before you jump or miss the mark.
|
||||
Pack the kits and don't forget the salt.
|
||||
The square peg will settle in the round hole.
|
||||
Fine soap saves tender skin.
|
||||
Poached eggs and tea must suffice.
|
||||
Bad nerves are jangled by a door slam.
|
||||
Ship maps are different from those for planes.
|
||||
Dimes showered down from all sides.
|
||||
They sang the same tunes at each party.
|
||||
The sky in the west is tinged with orange red.
|
||||
The pods of peas ferment in bare fields.
|
||||
The horse balked and threw the tall rider.
|
||||
The hitch between the horse and cart broke.
|
||||
Pile the coal high in the shed corner.
|
||||
A gold vase is both rare and costly.
|
||||
The knife was hung inside its bright sheath.
|
||||
The rarest spice comes from the far East.
|
||||
The roof should be tilted at a sharp slant.
|
||||
A smatter of French is worse than none.
|
||||
The mule trod the treadmill day and night.
|
||||
The aim of the contest is to raise a great fund.
|
||||
To send it now in large amounts is bad.
|
||||
There is a fine hard tang in salty air.
|
||||
Cod is the main business of the north shore.
|
||||
The slab was hewn from heavy blocks of slate.
|
||||
Dunk the stale biscuits into strong drink.
|
||||
Hang tinsel from both branches.
|
||||
Cap the jar with a tight brass cover.
|
||||
The poor boy missed the boat again.
|
||||
Be sure to set the lamp firmly in the hole.
|
||||
Pick a card and slip it under the pack.
|
||||
A round mat will cover the dull spot.
|
||||
The first part of the plan needs changing.
|
||||
A good book informs of what we ought to know.
|
||||
The mail comes in three batches per day.
|
||||
You cannot brew tea in a cold pot.
|
||||
Dots of light betrayed the black cat.
|
||||
Put the chart on the mantel and tack it down.
|
||||
The night shift men rate extra pay.
|
||||
The red paper brightened the dim stage.
|
||||
See the player scoot to third base.
|
||||
Slide the bill between the two leaves.
|
||||
Many hands help get the job done.
|
||||
We don't like to admit our small faults.
|
||||
No doubt about the way the wind blows.
|
||||
Dig deep in the earth for pirate's gold.
|
||||
The steady drip is worse than a drenching rain.
|
||||
A flat pack takes less luggage space.
|
||||
Green ice frosted the punch bowl.
|
||||
A stuffed chair slipped from the moving van.
|
||||
The stitch will serve but needs to be shortened.
|
||||
A thin book fits in the side pocket.
|
||||
The gloss on top made it unfit to read.
|
||||
The hail pattered on the burnt brown grass.
|
||||
Seven seals were stamped on great sheets.
|
||||
Our troops are set to strike heavy blows.
|
||||
The store was jammed before the sale could start.
|
||||
It was a bad error on the part of the new judge.
|
||||
One step more and the board will collapse.
|
||||
Take the match and strike it against your shoe.
|
||||
The pot boiled, but the contents failed to jell.
|
||||
The baby puts his right foot in his mouth.
|
||||
The bombs left most of the town in ruins.
|
||||
Stop and stare at the hard working man.
|
||||
The streets are narrow and full of sharp turns.
|
||||
The pup jerked the leash as he saw a feline shape.
|
||||
Open your book to the first page.
|
||||
Fish evade the net and swim off.
|
||||
Dip the pail once and let it settle.
|
||||
Will you please answer that phone.
|
||||
The big red apple fell to the ground.
|
||||
The curtain rose and the show was on.
|
||||
The young prince became heir to the throne.
|
||||
He sent the boy on a short errand.
|
||||
Leave now and you will arrive on time.
|
||||
The corner store was robbed last night.
|
||||
A gold ring will please most any girl.
|
||||
The long journey home took a year.
|
||||
She saw a cat in the neighbor's house.
|
||||
A pink shell was found on the sandy beach.
|
||||
Small children came to see him.
|
||||
The grass and bushes were wet with dew.
|
||||
The blind man counted his old coins.
|
||||
A severe storm tore down the barn.
|
||||
She called his name many times.
|
||||
When you hear the bell, come quickly.
|
||||
@@ -1,18 +0,0 @@
|
||||
{
|
||||
"Arabic": "ar",
|
||||
"Chinese": "zh-cn",
|
||||
"Czech": "cs",
|
||||
"Dutch": "nl",
|
||||
"English": "en",
|
||||
"French": "fr",
|
||||
"German": "de",
|
||||
"Hungarian": "hu",
|
||||
"Italian": "it",
|
||||
"Japanese": "ja",
|
||||
"Korean": "ko",
|
||||
"Polish": "pl",
|
||||
"Portuguese": "pt",
|
||||
"Russian": "ru",
|
||||
"Spanish": "es",
|
||||
"Turkish": "tr"
|
||||
}
|
||||
|
Before Width: | Height: | Size: 1.1 KiB |
@@ -1,869 +0,0 @@
|
||||
import os
|
||||
import re
|
||||
import textwrap
|
||||
from functools import cached_property
|
||||
|
||||
import pypinyin
|
||||
import torch
|
||||
from hangul_romanize import Transliter
|
||||
from hangul_romanize.rule import academic
|
||||
from num2words import num2words
|
||||
from spacy.lang.ar import Arabic
|
||||
from spacy.lang.en import English
|
||||
from spacy.lang.es import Spanish
|
||||
from spacy.lang.ja import Japanese
|
||||
from spacy.lang.zh import Chinese
|
||||
from tokenizers import Tokenizer
|
||||
|
||||
from TTS.tts.layers.xtts.zh_num2words import TextNorm as zh_num2words
|
||||
|
||||
|
||||
def get_spacy_lang(lang):
|
||||
if lang == "zh":
|
||||
return Chinese()
|
||||
elif lang == "ja":
|
||||
return Japanese()
|
||||
elif lang == "ar":
|
||||
return Arabic()
|
||||
elif lang == "es":
|
||||
return Spanish()
|
||||
else:
|
||||
# For most languages, Enlish does the job
|
||||
return English()
|
||||
|
||||
|
||||
def split_sentence(text, lang, text_split_length=250):
|
||||
"""Preprocess the input text"""
|
||||
text_splits = []
|
||||
if text_split_length is not None and len(text) >= text_split_length:
|
||||
text_splits.append("")
|
||||
nlp = get_spacy_lang(lang)
|
||||
nlp.add_pipe("sentencizer")
|
||||
doc = nlp(text)
|
||||
for sentence in doc.sents:
|
||||
if len(text_splits[-1]) + len(str(sentence)) <= text_split_length:
|
||||
# if the last sentence + the current sentence is less than the text_split_length
|
||||
# then add the current sentence to the last sentence
|
||||
text_splits[-1] += " " + str(sentence)
|
||||
text_splits[-1] = text_splits[-1].lstrip()
|
||||
elif len(str(sentence)) > text_split_length:
|
||||
# if the current sentence is greater than the text_split_length
|
||||
for line in textwrap.wrap(
|
||||
str(sentence),
|
||||
width=text_split_length,
|
||||
drop_whitespace=True,
|
||||
break_on_hyphens=False,
|
||||
tabsize=1,
|
||||
):
|
||||
text_splits.append(str(line))
|
||||
else:
|
||||
text_splits.append(str(sentence))
|
||||
|
||||
if len(text_splits) > 1:
|
||||
if text_splits[0] == "":
|
||||
del text_splits[0]
|
||||
else:
|
||||
text_splits = [text.lstrip()]
|
||||
|
||||
return text_splits
|
||||
|
||||
|
||||
_whitespace_re = re.compile(r"\s+")
|
||||
|
||||
# List of (regular expression, replacement) pairs for abbreviations:
|
||||
_abbreviations = {
|
||||
"en": [
|
||||
(re.compile("\\b%s\\." % x[0], re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
("mrs", "misess"),
|
||||
("mr", "mister"),
|
||||
("dr", "doctor"),
|
||||
("st", "saint"),
|
||||
("co", "company"),
|
||||
("jr", "junior"),
|
||||
("maj", "major"),
|
||||
("gen", "general"),
|
||||
("drs", "doctors"),
|
||||
("rev", "reverend"),
|
||||
("lt", "lieutenant"),
|
||||
("hon", "honorable"),
|
||||
("sgt", "sergeant"),
|
||||
("capt", "captain"),
|
||||
("esq", "esquire"),
|
||||
("ltd", "limited"),
|
||||
("col", "colonel"),
|
||||
("ft", "fort"),
|
||||
]
|
||||
],
|
||||
"es": [
|
||||
(re.compile("\\b%s\\." % x[0], re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
("sra", "señora"),
|
||||
("sr", "señor"),
|
||||
("dr", "doctor"),
|
||||
("dra", "doctora"),
|
||||
("st", "santo"),
|
||||
("co", "compañía"),
|
||||
("jr", "junior"),
|
||||
("ltd", "limitada"),
|
||||
]
|
||||
],
|
||||
"fr": [
|
||||
(re.compile("\\b%s\\." % x[0], re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
("mme", "madame"),
|
||||
("mr", "monsieur"),
|
||||
("dr", "docteur"),
|
||||
("st", "saint"),
|
||||
("co", "compagnie"),
|
||||
("jr", "junior"),
|
||||
("ltd", "limitée"),
|
||||
]
|
||||
],
|
||||
"de": [
|
||||
(re.compile("\\b%s\\." % x[0], re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
("fr", "frau"),
|
||||
("dr", "doktor"),
|
||||
("st", "sankt"),
|
||||
("co", "firma"),
|
||||
("jr", "junior"),
|
||||
]
|
||||
],
|
||||
"pt": [
|
||||
(re.compile("\\b%s\\." % x[0], re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
("sra", "senhora"),
|
||||
("sr", "senhor"),
|
||||
("dr", "doutor"),
|
||||
("dra", "doutora"),
|
||||
("st", "santo"),
|
||||
("co", "companhia"),
|
||||
("jr", "júnior"),
|
||||
("ltd", "limitada"),
|
||||
]
|
||||
],
|
||||
"it": [
|
||||
(re.compile("\\b%s\\." % x[0], re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
# ("sig.ra", "signora"),
|
||||
("sig", "signore"),
|
||||
("dr", "dottore"),
|
||||
("st", "santo"),
|
||||
("co", "compagnia"),
|
||||
("jr", "junior"),
|
||||
("ltd", "limitata"),
|
||||
]
|
||||
],
|
||||
"pl": [
|
||||
(re.compile("\\b%s\\." % x[0], re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
("p", "pani"),
|
||||
("m", "pan"),
|
||||
("dr", "doktor"),
|
||||
("sw", "święty"),
|
||||
("jr", "junior"),
|
||||
]
|
||||
],
|
||||
"ar": [
|
||||
(re.compile("\\b%s\\." % x[0], re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
# There are not many common abbreviations in Arabic as in English.
|
||||
]
|
||||
],
|
||||
"zh": [
|
||||
(re.compile("\\b%s\\." % x[0], re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
# Chinese doesn't typically use abbreviations in the same way as Latin-based scripts.
|
||||
]
|
||||
],
|
||||
"cs": [
|
||||
(re.compile("\\b%s\\." % x[0], re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
("dr", "doktor"), # doctor
|
||||
("ing", "inženýr"), # engineer
|
||||
("p", "pan"), # Could also map to pani for woman but no easy way to do it
|
||||
# Other abbreviations would be specialized and not as common.
|
||||
]
|
||||
],
|
||||
"ru": [
|
||||
(re.compile("\\b%s\\b" % x[0], re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
("г-жа", "госпожа"), # Mrs.
|
||||
("г-н", "господин"), # Mr.
|
||||
("д-р", "доктор"), # doctor
|
||||
# Other abbreviations are less common or specialized.
|
||||
]
|
||||
],
|
||||
"nl": [
|
||||
(re.compile("\\b%s\\." % x[0], re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
("dhr", "de heer"), # Mr.
|
||||
("mevr", "mevrouw"), # Mrs.
|
||||
("dr", "dokter"), # doctor
|
||||
("jhr", "jonkheer"), # young lord or nobleman
|
||||
# Dutch uses more abbreviations, but these are the most common ones.
|
||||
]
|
||||
],
|
||||
"tr": [
|
||||
(re.compile("\\b%s\\." % x[0], re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
("b", "bay"), # Mr.
|
||||
("byk", "büyük"), # büyük
|
||||
("dr", "doktor"), # doctor
|
||||
# Add other Turkish abbreviations here if needed.
|
||||
]
|
||||
],
|
||||
"hu": [
|
||||
(re.compile("\\b%s\\." % x[0], re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
("dr", "doktor"), # doctor
|
||||
("b", "bácsi"), # Mr.
|
||||
("nőv", "nővér"), # nurse
|
||||
# Add other Hungarian abbreviations here if needed.
|
||||
]
|
||||
],
|
||||
"ko": [
|
||||
(re.compile("\\b%s\\." % x[0], re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
# Korean doesn't typically use abbreviations in the same way as Latin-based scripts.
|
||||
]
|
||||
],
|
||||
"ja": [
|
||||
(re.compile("\\b%s\\b" % x[0]), x[1])
|
||||
for x in [
|
||||
("氏", "さん"), # Mr.
|
||||
("夫人", "おんなのひと"), # Mrs.
|
||||
("博士", "はかせ"), # Doctor or PhD
|
||||
("株", "株式会社"), # Corporation
|
||||
("有", "有限会社"), # Limited company
|
||||
("大学", "だいがく"), # University
|
||||
("先生", "せんせい"), # Teacher/Professor/Master
|
||||
("君", "くん") # Used at the end of boys' names to express familiarity or affection.
|
||||
]
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
def expand_abbreviations_multilingual(text, lang="en"):
|
||||
for regex, replacement in _abbreviations[lang]:
|
||||
text = re.sub(regex, replacement, text)
|
||||
return text
|
||||
|
||||
|
||||
_symbols_multilingual = {
|
||||
"en": [
|
||||
(re.compile(r"%s" % re.escape(x[0]), re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
("&", " and "),
|
||||
("@", " at "),
|
||||
("%", " percent "),
|
||||
("#", " hash "),
|
||||
("$", " dollar "),
|
||||
("£", " pound "),
|
||||
("°", " degree "),
|
||||
]
|
||||
],
|
||||
"es": [
|
||||
(re.compile(r"%s" % re.escape(x[0]), re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
("&", " y "),
|
||||
("@", " arroba "),
|
||||
("%", " por ciento "),
|
||||
("#", " numeral "),
|
||||
("$", " dolar "),
|
||||
("£", " libra "),
|
||||
("°", " grados "),
|
||||
]
|
||||
],
|
||||
"fr": [
|
||||
(re.compile(r"%s" % re.escape(x[0]), re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
("&", " et "),
|
||||
("@", " arobase "),
|
||||
("%", " pour cent "),
|
||||
("#", " dièse "),
|
||||
("$", " dollar "),
|
||||
("£", " livre "),
|
||||
("°", " degrés "),
|
||||
]
|
||||
],
|
||||
"de": [
|
||||
(re.compile(r"%s" % re.escape(x[0]), re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
("&", " und "),
|
||||
("@", " at "),
|
||||
("%", " prozent "),
|
||||
("#", " raute "),
|
||||
("$", " dollar "),
|
||||
("£", " pfund "),
|
||||
("°", " grad "),
|
||||
]
|
||||
],
|
||||
"pt": [
|
||||
(re.compile(r"%s" % re.escape(x[0]), re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
("&", " e "),
|
||||
("@", " arroba "),
|
||||
("%", " por cento "),
|
||||
("#", " cardinal "),
|
||||
("$", " dólar "),
|
||||
("£", " libra "),
|
||||
("°", " graus "),
|
||||
]
|
||||
],
|
||||
"it": [
|
||||
(re.compile(r"%s" % re.escape(x[0]), re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
("&", " e "),
|
||||
("@", " chiocciola "),
|
||||
("%", " per cento "),
|
||||
("#", " cancelletto "),
|
||||
("$", " dollaro "),
|
||||
("£", " sterlina "),
|
||||
("°", " gradi "),
|
||||
]
|
||||
],
|
||||
"pl": [
|
||||
(re.compile(r"%s" % re.escape(x[0]), re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
("&", " i "),
|
||||
("@", " małpa "),
|
||||
("%", " procent "),
|
||||
("#", " krzyżyk "),
|
||||
("$", " dolar "),
|
||||
("£", " funt "),
|
||||
("°", " stopnie "),
|
||||
]
|
||||
],
|
||||
"ar": [
|
||||
# Arabic
|
||||
(re.compile(r"%s" % re.escape(x[0]), re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
("&", " و "),
|
||||
("@", " على "),
|
||||
("%", " في المئة "),
|
||||
("#", " رقم "),
|
||||
("$", " دولار "),
|
||||
("£", " جنيه "),
|
||||
("°", " درجة "),
|
||||
]
|
||||
],
|
||||
"zh": [
|
||||
# Chinese
|
||||
(re.compile(r"%s" % re.escape(x[0]), re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
("&", " 和 "),
|
||||
("@", " 在 "),
|
||||
("%", " 百分之 "),
|
||||
("#", " 号 "),
|
||||
("$", " 美元 "),
|
||||
("£", " 英镑 "),
|
||||
("°", " 度 "),
|
||||
]
|
||||
],
|
||||
"cs": [
|
||||
# Czech
|
||||
(re.compile(r"%s" % re.escape(x[0]), re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
("&", " a "),
|
||||
("@", " na "),
|
||||
("%", " procento "),
|
||||
("#", " křížek "),
|
||||
("$", " dolar "),
|
||||
("£", " libra "),
|
||||
("°", " stupně "),
|
||||
]
|
||||
],
|
||||
"ru": [
|
||||
# Russian
|
||||
(re.compile(r"%s" % re.escape(x[0]), re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
("&", " и "),
|
||||
("@", " собака "),
|
||||
("%", " процентов "),
|
||||
("#", " номер "),
|
||||
("$", " доллар "),
|
||||
("£", " фунт "),
|
||||
("°", " градус "),
|
||||
]
|
||||
],
|
||||
"nl": [
|
||||
# Dutch
|
||||
(re.compile(r"%s" % re.escape(x[0]), re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
("&", " en "),
|
||||
("@", " bij "),
|
||||
("%", " procent "),
|
||||
("#", " hekje "),
|
||||
("$", " dollar "),
|
||||
("£", " pond "),
|
||||
("°", " graden "),
|
||||
]
|
||||
],
|
||||
"tr": [
|
||||
(re.compile(r"%s" % re.escape(x[0]), re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
("&", " ve "),
|
||||
("@", " at "),
|
||||
("%", " yüzde "),
|
||||
("#", " diyez "),
|
||||
("$", " dolar "),
|
||||
("£", " sterlin "),
|
||||
("°", " derece "),
|
||||
]
|
||||
],
|
||||
"hu": [
|
||||
(re.compile(r"%s" % re.escape(x[0]), re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
("&", " és "),
|
||||
("@", " kukac "),
|
||||
("%", " százalék "),
|
||||
("#", " kettőskereszt "),
|
||||
("$", " dollár "),
|
||||
("£", " font "),
|
||||
("°", " fok "),
|
||||
]
|
||||
],
|
||||
"ko": [
|
||||
# Korean
|
||||
(re.compile(r"%s" % re.escape(x[0]), re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
("&", " 그리고 "),
|
||||
("@", " 에 "),
|
||||
("%", " 퍼센트 "),
|
||||
("#", " 번호 "),
|
||||
("$", " 달러 "),
|
||||
("£", " 파운드 "),
|
||||
("°", " 도 "),
|
||||
]
|
||||
],
|
||||
"ja": [
|
||||
(re.compile(r"%s" % re.escape(x[0])), x[1])
|
||||
for x in [
|
||||
("&", " と "),
|
||||
("@", " アットマーク "),
|
||||
("%", " パーセント "),
|
||||
("#", " ナンバー "),
|
||||
("$", " ドル "),
|
||||
("£", " ポンド "),
|
||||
("°", " 度"),
|
||||
]
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
def expand_symbols_multilingual(text, lang="en"):
|
||||
for regex, replacement in _symbols_multilingual[lang]:
|
||||
text = re.sub(regex, replacement, text)
|
||||
text = text.replace(" ", " ") # Ensure there are no double spaces
|
||||
return text.strip()
|
||||
|
||||
|
||||
_ordinal_re = {
|
||||
"en": re.compile(r"([0-9]+)(st|nd|rd|th)"),
|
||||
"es": re.compile(r"([0-9]+)(º|ª|er|o|a|os|as)"),
|
||||
"fr": re.compile(r"([0-9]+)(º|ª|er|re|e|ème)"),
|
||||
"de": re.compile(r"([0-9]+)(st|nd|rd|th|º|ª|\.(?=\s|$))"),
|
||||
"pt": re.compile(r"([0-9]+)(º|ª|o|a|os|as)"),
|
||||
"it": re.compile(r"([0-9]+)(º|°|ª|o|a|i|e)"),
|
||||
"pl": re.compile(r"([0-9]+)(º|ª|st|nd|rd|th)"),
|
||||
"ar": re.compile(r"([0-9]+)(ون|ين|ث|ر|ى)"),
|
||||
"cs": re.compile(r"([0-9]+)\.(?=\s|$)"), # In Czech, a dot is often used after the number to indicate ordinals.
|
||||
"ru": re.compile(r"([0-9]+)(-й|-я|-е|-ое|-ье|-го)"),
|
||||
"nl": re.compile(r"([0-9]+)(de|ste|e)"),
|
||||
"tr": re.compile(r"([0-9]+)(\.|inci|nci|uncu|üncü|\.)"),
|
||||
"hu": re.compile(r"([0-9]+)(\.|adik|edik|odik|edik|ödik|ödike|ik)"),
|
||||
"ko": re.compile(r"([0-9]+)(번째|번|차|째)"),
|
||||
"ja": re.compile(r"([0-9]+)(番|回|つ|目|等|位)")
|
||||
}
|
||||
_number_re = re.compile(r"[0-9]+")
|
||||
_currency_re = {
|
||||
"USD": re.compile(r"((\$[0-9\.\,]*[0-9]+)|([0-9\.\,]*[0-9]+\$))"),
|
||||
"GBP": re.compile(r"((£[0-9\.\,]*[0-9]+)|([0-9\.\,]*[0-9]+£))"),
|
||||
"EUR": re.compile(r"(([0-9\.\,]*[0-9]+€)|((€[0-9\.\,]*[0-9]+)))"),
|
||||
}
|
||||
|
||||
_comma_number_re = re.compile(r"\b\d{1,3}(,\d{3})*(\.\d+)?\b")
|
||||
_dot_number_re = re.compile(r"\b\d{1,3}(.\d{3})*(\,\d+)?\b")
|
||||
_decimal_number_re = re.compile(r"([0-9]+[.,][0-9]+)")
|
||||
|
||||
|
||||
def _remove_commas(m):
|
||||
text = m.group(0)
|
||||
if "," in text:
|
||||
text = text.replace(",", "")
|
||||
return text
|
||||
|
||||
|
||||
def _remove_dots(m):
|
||||
text = m.group(0)
|
||||
if "." in text:
|
||||
text = text.replace(".", "")
|
||||
return text
|
||||
|
||||
|
||||
def _expand_decimal_point(m, lang="en"):
|
||||
amount = m.group(1).replace(",", ".")
|
||||
return num2words(float(amount), lang=lang if lang != "cs" else "cz")
|
||||
|
||||
|
||||
def _expand_currency(m, lang="en", currency="USD"):
|
||||
amount = float((re.sub(r"[^\d.]", "", m.group(0).replace(",", "."))))
|
||||
full_amount = num2words(amount, to="currency", currency=currency, lang=lang if lang != "cs" else "cz")
|
||||
|
||||
and_equivalents = {
|
||||
"en": ", ",
|
||||
"es": " con ",
|
||||
"fr": " et ",
|
||||
"de": " und ",
|
||||
"pt": " e ",
|
||||
"it": " e ",
|
||||
"pl": ", ",
|
||||
"cs": ", ",
|
||||
"ru": ", ",
|
||||
"nl": ", ",
|
||||
"ar": ", ",
|
||||
"tr": ", ",
|
||||
"hu": ", ",
|
||||
"ko": ", ",
|
||||
}
|
||||
|
||||
if amount.is_integer():
|
||||
last_and = full_amount.rfind(and_equivalents[lang])
|
||||
if last_and != -1:
|
||||
full_amount = full_amount[:last_and]
|
||||
|
||||
return full_amount
|
||||
|
||||
|
||||
def _expand_ordinal(m, lang="en"):
|
||||
return num2words(int(m.group(1)), ordinal=True, lang=lang if lang != "cs" else "cz")
|
||||
|
||||
|
||||
def _expand_number(m, lang="en"):
|
||||
return num2words(int(m.group(0)), lang=lang if lang != "cs" else "cz")
|
||||
|
||||
|
||||
def expand_numbers_multilingual(text, lang="en"):
|
||||
if lang == "zh":
|
||||
text = zh_num2words()(text)
|
||||
else:
|
||||
if lang in ["en", "ru"]:
|
||||
text = re.sub(_comma_number_re, _remove_commas, text)
|
||||
else:
|
||||
text = re.sub(_dot_number_re, _remove_dots, text)
|
||||
try:
|
||||
text = re.sub(_currency_re["GBP"], lambda m: _expand_currency(m, lang, "GBP"), text)
|
||||
text = re.sub(_currency_re["USD"], lambda m: _expand_currency(m, lang, "USD"), text)
|
||||
text = re.sub(_currency_re["EUR"], lambda m: _expand_currency(m, lang, "EUR"), text)
|
||||
except:
|
||||
pass
|
||||
if lang != "tr":
|
||||
text = re.sub(_decimal_number_re, lambda m: _expand_decimal_point(m, lang), text)
|
||||
text = re.sub(_ordinal_re[lang], lambda m: _expand_ordinal(m, lang), text)
|
||||
text = re.sub(_number_re, lambda m: _expand_number(m, lang), text)
|
||||
return text
|
||||
|
||||
|
||||
def lowercase(text):
|
||||
return text.lower()
|
||||
|
||||
|
||||
def collapse_whitespace(text):
|
||||
return re.sub(_whitespace_re, " ", text)
|
||||
|
||||
|
||||
def multilingual_cleaners(text, lang):
|
||||
text = text.replace('"', "")
|
||||
if lang == "tr":
|
||||
text = text.replace("İ", "i")
|
||||
text = text.replace("Ö", "ö")
|
||||
text = text.replace("Ü", "ü")
|
||||
text = lowercase(text)
|
||||
text = expand_numbers_multilingual(text, lang)
|
||||
text = expand_abbreviations_multilingual(text, lang)
|
||||
text = expand_symbols_multilingual(text, lang=lang)
|
||||
text = collapse_whitespace(text)
|
||||
return text
|
||||
|
||||
|
||||
def basic_cleaners(text):
|
||||
"""Basic pipeline that lowercases and collapses whitespace without transliteration."""
|
||||
text = lowercase(text)
|
||||
text = collapse_whitespace(text)
|
||||
return text
|
||||
|
||||
|
||||
def chinese_transliterate(text):
|
||||
return "".join(
|
||||
[p[0] for p in pypinyin.pinyin(text, style=pypinyin.Style.TONE3, heteronym=False, neutral_tone_with_five=True)]
|
||||
)
|
||||
|
||||
|
||||
def japanese_cleaners(text, katsu):
|
||||
text = katsu.romaji(text)
|
||||
text = lowercase(text)
|
||||
return text
|
||||
|
||||
|
||||
def korean_transliterate(text):
|
||||
r = Transliter(academic)
|
||||
return r.translit(text)
|
||||
|
||||
|
||||
DEFAULT_VOCAB_FILE = os.path.join(os.path.dirname(os.path.realpath(__file__)), "../data/tokenizer.json")
|
||||
|
||||
|
||||
class VoiceBpeTokenizer:
|
||||
def __init__(self, vocab_file=None):
|
||||
self.tokenizer = None
|
||||
if vocab_file is not None:
|
||||
self.tokenizer = Tokenizer.from_file(vocab_file)
|
||||
self.char_limits = {
|
||||
"en": 250,
|
||||
"de": 253,
|
||||
"fr": 273,
|
||||
"es": 239,
|
||||
"it": 213,
|
||||
"pt": 203,
|
||||
"pl": 224,
|
||||
"zh": 82,
|
||||
"ar": 166,
|
||||
"cs": 186,
|
||||
"ru": 182,
|
||||
"nl": 251,
|
||||
"tr": 226,
|
||||
"ja": 71,
|
||||
"hu": 224,
|
||||
"ko": 95,
|
||||
}
|
||||
|
||||
@cached_property
|
||||
def katsu(self):
|
||||
import cutlet
|
||||
|
||||
return cutlet.Cutlet()
|
||||
|
||||
def check_input_length(self, txt, lang):
|
||||
lang = lang.split("-")[0] # remove the region
|
||||
limit = self.char_limits.get(lang, 250)
|
||||
if len(txt) > limit:
|
||||
print(
|
||||
f"[!] Warning: The text length exceeds the character limit of {limit} for language '{lang}', this might cause truncated audio."
|
||||
)
|
||||
|
||||
def preprocess_text(self, txt, lang):
|
||||
if lang in {"ar", "cs", "de", "en", "es", "fr", "hu", "it", "nl", "pl", "pt", "ru", "tr", "zh", "ko"}:
|
||||
txt = multilingual_cleaners(txt, lang)
|
||||
if lang == "zh":
|
||||
txt = chinese_transliterate(txt)
|
||||
if lang == "ko":
|
||||
txt = korean_transliterate(txt)
|
||||
elif lang == "ja":
|
||||
txt = japanese_cleaners(txt, self.katsu)
|
||||
elif lang == "hi":
|
||||
# @manmay will implement this
|
||||
txt = basic_cleaners(txt)
|
||||
else:
|
||||
raise NotImplementedError(f"Language '{lang}' is not supported.")
|
||||
return txt
|
||||
|
||||
def encode(self, txt, lang):
|
||||
lang = lang.split("-")[0] # remove the region
|
||||
self.check_input_length(txt, lang)
|
||||
txt = self.preprocess_text(txt, lang)
|
||||
lang = "zh-cn" if lang == "zh" else lang
|
||||
txt = f"[{lang}]{txt}"
|
||||
txt = txt.replace(" ", "[SPACE]")
|
||||
return self.tokenizer.encode(txt).ids
|
||||
|
||||
def decode(self, seq):
|
||||
if isinstance(seq, torch.Tensor):
|
||||
seq = seq.cpu().numpy()
|
||||
txt = self.tokenizer.decode(seq, skip_special_tokens=False).replace(" ", "")
|
||||
txt = txt.replace("[SPACE]", " ")
|
||||
txt = txt.replace("[STOP]", "")
|
||||
txt = txt.replace("[UNK]", "")
|
||||
return txt
|
||||
|
||||
def __len__(self):
|
||||
return self.tokenizer.get_vocab_size()
|
||||
|
||||
def get_number_tokens(self):
|
||||
return max(self.tokenizer.get_vocab().values()) + 1
|
||||
|
||||
|
||||
def test_expand_numbers_multilingual():
|
||||
test_cases = [
|
||||
# English
|
||||
("In 12.5 seconds.", "In twelve point five seconds.", "en"),
|
||||
("There were 50 soldiers.", "There were fifty soldiers.", "en"),
|
||||
("This is a 1st test", "This is a first test", "en"),
|
||||
("That will be $20 sir.", "That will be twenty dollars sir.", "en"),
|
||||
("That will be 20€ sir.", "That will be twenty euro sir.", "en"),
|
||||
("That will be 20.15€ sir.", "That will be twenty euro, fifteen cents sir.", "en"),
|
||||
("That's 100,000.5.", "That's one hundred thousand point five.", "en"),
|
||||
# French
|
||||
("En 12,5 secondes.", "En douze virgule cinq secondes.", "fr"),
|
||||
("Il y avait 50 soldats.", "Il y avait cinquante soldats.", "fr"),
|
||||
("Ceci est un 1er test", "Ceci est un premier test", "fr"),
|
||||
("Cela vous fera $20 monsieur.", "Cela vous fera vingt dollars monsieur.", "fr"),
|
||||
("Cela vous fera 20€ monsieur.", "Cela vous fera vingt euros monsieur.", "fr"),
|
||||
("Cela vous fera 20,15€ monsieur.", "Cela vous fera vingt euros et quinze centimes monsieur.", "fr"),
|
||||
("Ce sera 100.000,5.", "Ce sera cent mille virgule cinq.", "fr"),
|
||||
# German
|
||||
("In 12,5 Sekunden.", "In zwölf Komma fünf Sekunden.", "de"),
|
||||
("Es gab 50 Soldaten.", "Es gab fünfzig Soldaten.", "de"),
|
||||
("Dies ist ein 1. Test", "Dies ist ein erste Test", "de"), # Issue with gender
|
||||
("Das macht $20 Herr.", "Das macht zwanzig Dollar Herr.", "de"),
|
||||
("Das macht 20€ Herr.", "Das macht zwanzig Euro Herr.", "de"),
|
||||
("Das macht 20,15€ Herr.", "Das macht zwanzig Euro und fünfzehn Cent Herr.", "de"),
|
||||
# Spanish
|
||||
("En 12,5 segundos.", "En doce punto cinco segundos.", "es"),
|
||||
("Había 50 soldados.", "Había cincuenta soldados.", "es"),
|
||||
("Este es un 1er test", "Este es un primero test", "es"),
|
||||
("Eso le costará $20 señor.", "Eso le costará veinte dólares señor.", "es"),
|
||||
("Eso le costará 20€ señor.", "Eso le costará veinte euros señor.", "es"),
|
||||
("Eso le costará 20,15€ señor.", "Eso le costará veinte euros con quince céntimos señor.", "es"),
|
||||
# Italian
|
||||
("In 12,5 secondi.", "In dodici virgola cinque secondi.", "it"),
|
||||
("C'erano 50 soldati.", "C'erano cinquanta soldati.", "it"),
|
||||
("Questo è un 1° test", "Questo è un primo test", "it"),
|
||||
("Ti costerà $20 signore.", "Ti costerà venti dollari signore.", "it"),
|
||||
("Ti costerà 20€ signore.", "Ti costerà venti euro signore.", "it"),
|
||||
("Ti costerà 20,15€ signore.", "Ti costerà venti euro e quindici centesimi signore.", "it"),
|
||||
# Portuguese
|
||||
("Em 12,5 segundos.", "Em doze vírgula cinco segundos.", "pt"),
|
||||
("Havia 50 soldados.", "Havia cinquenta soldados.", "pt"),
|
||||
("Este é um 1º teste", "Este é um primeiro teste", "pt"),
|
||||
("Isso custará $20 senhor.", "Isso custará vinte dólares senhor.", "pt"),
|
||||
("Isso custará 20€ senhor.", "Isso custará vinte euros senhor.", "pt"),
|
||||
(
|
||||
"Isso custará 20,15€ senhor.",
|
||||
"Isso custará vinte euros e quinze cêntimos senhor.",
|
||||
"pt",
|
||||
), # "cêntimos" should be "centavos" num2words issue
|
||||
# Polish
|
||||
("W 12,5 sekundy.", "W dwanaście przecinek pięć sekundy.", "pl"),
|
||||
("Było 50 żołnierzy.", "Było pięćdziesiąt żołnierzy.", "pl"),
|
||||
("To będzie kosztować 20€ panie.", "To będzie kosztować dwadzieścia euro panie.", "pl"),
|
||||
("To będzie kosztować 20,15€ panie.", "To będzie kosztować dwadzieścia euro, piętnaście centów panie.", "pl"),
|
||||
# Arabic
|
||||
("في الـ 12,5 ثانية.", "في الـ اثنا عشر , خمسون ثانية.", "ar"),
|
||||
("كان هناك 50 جنديًا.", "كان هناك خمسون جنديًا.", "ar"),
|
||||
# ("ستكون النتيجة $20 يا سيد.", 'ستكون النتيجة عشرون دولار يا سيد.', 'ar'), # $ and € are mising from num2words
|
||||
# ("ستكون النتيجة 20€ يا سيد.", 'ستكون النتيجة عشرون يورو يا سيد.', 'ar'),
|
||||
# Czech
|
||||
("Za 12,5 vteřiny.", "Za dvanáct celá pět vteřiny.", "cs"),
|
||||
("Bylo tam 50 vojáků.", "Bylo tam padesát vojáků.", "cs"),
|
||||
("To bude stát 20€ pane.", "To bude stát dvacet euro pane.", "cs"),
|
||||
("To bude 20.15€ pane.", "To bude dvacet euro, patnáct centů pane.", "cs"),
|
||||
# Russian
|
||||
("Через 12.5 секунды.", "Через двенадцать запятая пять секунды.", "ru"),
|
||||
("Там было 50 солдат.", "Там было пятьдесят солдат.", "ru"),
|
||||
("Это будет 20.15€ сэр.", "Это будет двадцать евро, пятнадцать центов сэр.", "ru"),
|
||||
("Это будет стоить 20€ господин.", "Это будет стоить двадцать евро господин.", "ru"),
|
||||
# Dutch
|
||||
("In 12,5 seconden.", "In twaalf komma vijf seconden.", "nl"),
|
||||
("Er waren 50 soldaten.", "Er waren vijftig soldaten.", "nl"),
|
||||
("Dat wordt dan $20 meneer.", "Dat wordt dan twintig dollar meneer.", "nl"),
|
||||
("Dat wordt dan 20€ meneer.", "Dat wordt dan twintig euro meneer.", "nl"),
|
||||
# Chinese (Simplified)
|
||||
("在12.5秒内", "在十二点五秒内", "zh"),
|
||||
("有50名士兵", "有五十名士兵", "zh"),
|
||||
# ("那将是$20先生", '那将是二十美元先生', 'zh'), currency doesn't work
|
||||
# ("那将是20€先生", '那将是二十欧元先生', 'zh'),
|
||||
# Turkish
|
||||
# ("12,5 saniye içinde.", 'On iki virgül beş saniye içinde.', 'tr'), # decimal doesn't work for TR
|
||||
("50 asker vardı.", "elli asker vardı.", "tr"),
|
||||
("Bu 1. test", "Bu birinci test", "tr"),
|
||||
# ("Bu 100.000,5.", 'Bu yüz bin virgül beş.', 'tr'),
|
||||
# Hungarian
|
||||
("12,5 másodperc alatt.", "tizenkettő egész öt tized másodperc alatt.", "hu"),
|
||||
("50 katona volt.", "ötven katona volt.", "hu"),
|
||||
("Ez az 1. teszt", "Ez az első teszt", "hu"),
|
||||
# Korean
|
||||
("12.5 초 안에.", "십이 점 다섯 초 안에.", "ko"),
|
||||
("50 명의 병사가 있었다.", "오십 명의 병사가 있었다.", "ko"),
|
||||
("이것은 1 번째 테스트입니다", "이것은 첫 번째 테스트입니다", "ko"),
|
||||
]
|
||||
for a, b, lang in test_cases:
|
||||
out = expand_numbers_multilingual(a, lang=lang)
|
||||
assert out == b, f"'{out}' vs '{b}'"
|
||||
|
||||
|
||||
def test_abbreviations_multilingual():
|
||||
test_cases = [
|
||||
# English
|
||||
("Hello Mr. Smith.", "Hello mister Smith.", "en"),
|
||||
("Dr. Jones is here.", "doctor Jones is here.", "en"),
|
||||
# Spanish
|
||||
("Hola Sr. Garcia.", "Hola señor Garcia.", "es"),
|
||||
("La Dra. Martinez es muy buena.", "La doctora Martinez es muy buena.", "es"),
|
||||
# French
|
||||
("Bonjour Mr. Dupond.", "Bonjour monsieur Dupond.", "fr"),
|
||||
("Mme. Moreau est absente aujourd'hui.", "madame Moreau est absente aujourd'hui.", "fr"),
|
||||
# German
|
||||
("Frau Dr. Müller ist sehr klug.", "Frau doktor Müller ist sehr klug.", "de"),
|
||||
# Portuguese
|
||||
("Olá Sr. Silva.", "Olá senhor Silva.", "pt"),
|
||||
("Dra. Costa, você está disponível?", "doutora Costa, você está disponível?", "pt"),
|
||||
# Italian
|
||||
("Buongiorno, Sig. Rossi.", "Buongiorno, signore Rossi.", "it"),
|
||||
# ("Sig.ra Bianchi, posso aiutarti?", 'signora Bianchi, posso aiutarti?', 'it'), # Issue with matching that pattern
|
||||
# Polish
|
||||
("Dzień dobry, P. Kowalski.", "Dzień dobry, pani Kowalski.", "pl"),
|
||||
("M. Nowak, czy mogę zadać pytanie?", "pan Nowak, czy mogę zadać pytanie?", "pl"),
|
||||
# Czech
|
||||
("P. Novák", "pan Novák", "cs"),
|
||||
("Dr. Vojtěch", "doktor Vojtěch", "cs"),
|
||||
# Dutch
|
||||
("Dhr. Jansen", "de heer Jansen", "nl"),
|
||||
("Mevr. de Vries", "mevrouw de Vries", "nl"),
|
||||
# Russian
|
||||
("Здравствуйте Г-н Иванов.", "Здравствуйте господин Иванов.", "ru"),
|
||||
("Д-р Смирнов здесь, чтобы увидеть вас.", "доктор Смирнов здесь, чтобы увидеть вас.", "ru"),
|
||||
# Turkish
|
||||
("Merhaba B. Yılmaz.", "Merhaba bay Yılmaz.", "tr"),
|
||||
("Dr. Ayşe burada.", "doktor Ayşe burada.", "tr"),
|
||||
# Hungarian
|
||||
("Dr. Szabó itt van.", "doktor Szabó itt van.", "hu"),
|
||||
]
|
||||
|
||||
for a, b, lang in test_cases:
|
||||
out = expand_abbreviations_multilingual(a, lang=lang)
|
||||
assert out == b, f"'{out}' vs '{b}'"
|
||||
|
||||
|
||||
def test_symbols_multilingual():
|
||||
test_cases = [
|
||||
("I have 14% battery", "I have 14 percent battery", "en"),
|
||||
("Te veo @ la fiesta", "Te veo arroba la fiesta", "es"),
|
||||
("J'ai 14° de fièvre", "J'ai 14 degrés de fièvre", "fr"),
|
||||
("Die Rechnung beträgt £ 20", "Die Rechnung beträgt pfund 20", "de"),
|
||||
("O meu email é ana&joao@gmail.com", "O meu email é ana e joao arroba gmail.com", "pt"),
|
||||
("linguaggio di programmazione C#", "linguaggio di programmazione C cancelletto", "it"),
|
||||
("Moja temperatura to 36.6°", "Moja temperatura to 36.6 stopnie", "pl"),
|
||||
("Mám 14% baterie", "Mám 14 procento baterie", "cs"),
|
||||
("Těším se na tebe @ party", "Těším se na tebe na party", "cs"),
|
||||
("У меня 14% заряда", "У меня 14 процентов заряда", "ru"),
|
||||
("Я буду @ дома", "Я буду собака дома", "ru"),
|
||||
("Ik heb 14% batterij", "Ik heb 14 procent batterij", "nl"),
|
||||
("Ik zie je @ het feest", "Ik zie je bij het feest", "nl"),
|
||||
("لدي 14% في البطارية", "لدي 14 في المئة في البطارية", "ar"),
|
||||
("我的电量为 14%", "我的电量为 14 百分之", "zh"),
|
||||
("Pilim %14 dolu.", "Pilim yüzde 14 dolu.", "tr"),
|
||||
("Az akkumulátorom töltöttsége 14%", "Az akkumulátorom töltöttsége 14 százalék", "hu"),
|
||||
("배터리 잔량이 14%입니다.", "배터리 잔량이 14 퍼센트입니다.", "ko"),
|
||||
]
|
||||
|
||||
for a, b, lang in test_cases:
|
||||
out = expand_symbols_multilingual(a, lang=lang)
|
||||
assert out == b, f"'{out}' vs '{b}'"
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_expand_numbers_multilingual()
|
||||
test_abbreviations_multilingual()
|
||||
test_symbols_multilingual()
|
||||
@@ -1,171 +0,0 @@
|
||||
absl-py==2.1.0
|
||||
aiofiles==23.2.1
|
||||
aiohttp==3.9.3
|
||||
aiosignal==1.3.1
|
||||
altair==5.2.0
|
||||
annotated-types==0.6.0
|
||||
anyascii==0.3.2
|
||||
anyio==4.3.0
|
||||
attrs==23.2.0
|
||||
audioread==3.0.1
|
||||
av==11.0.0
|
||||
Babel==2.14.0
|
||||
bangla==0.0.2
|
||||
blinker==1.7.0
|
||||
blis==0.7.11
|
||||
bnnumerizer==0.0.2
|
||||
bnunicodenormalizer==0.1.6
|
||||
catalogue==2.0.10
|
||||
certifi==2024.2.2
|
||||
cffi==1.16.0
|
||||
charset-normalizer==3.3.2
|
||||
click==8.1.7
|
||||
cloudpathlib==0.16.0
|
||||
colorama==0.4.6
|
||||
coloredlogs==15.0.1
|
||||
confection==0.1.4
|
||||
contourpy==1.2.0
|
||||
coqpit==0.0.17
|
||||
ctranslate2==4.1.0
|
||||
cutlet==0.4.0
|
||||
cycler==0.12.1
|
||||
cymem==2.0.8
|
||||
Cython==3.0.9
|
||||
dateparser==1.1.8
|
||||
decorator==5.1.1
|
||||
docopt==0.6.2
|
||||
einops==0.7.0
|
||||
encodec==0.1.1
|
||||
fastapi==0.110.0
|
||||
faster-whisper==1.0.1
|
||||
ffmpy==0.3.2
|
||||
filelock==3.13.3
|
||||
Flask==3.0.2
|
||||
flatbuffers==24.3.25
|
||||
fonttools==4.50.0
|
||||
frozenlist==1.4.1
|
||||
fsspec==2024.3.1
|
||||
fugashi==1.3.1
|
||||
fuzzywuzzy>=0.18.0
|
||||
g2pkk==0.1.2
|
||||
gradio==3.50.2
|
||||
gradio_client==0.6.1
|
||||
grpcio==1.62.1
|
||||
gruut==2.2.3
|
||||
gruut-ipa==0.13.0
|
||||
gruut-lang-de==2.0.0
|
||||
gruut-lang-en==2.0.0
|
||||
gruut-lang-es==2.0.0
|
||||
gruut-lang-fr==2.0.2
|
||||
h11==0.14.0
|
||||
hangul-romanize==0.1.0
|
||||
httpcore==1.0.4
|
||||
httpx==0.27.0
|
||||
huggingface-hub==0.22.1
|
||||
humanfriendly==10.0
|
||||
idna==3.6
|
||||
importlib_metadata==7.1.0
|
||||
importlib_resources==6.4.0
|
||||
inflect==7.0.0
|
||||
itsdangerous==2.1.2
|
||||
jaconv==0.3.4
|
||||
jamo==0.4.1
|
||||
jieba==0.42.1
|
||||
Jinja2==3.1.3
|
||||
joblib==1.3.2
|
||||
jsonlines==1.2.0
|
||||
jsonschema==4.21.1
|
||||
jsonschema-specifications==2023.12.1
|
||||
kiwisolver==1.4.5
|
||||
langcodes==3.3.0
|
||||
lazy_loader==0.3
|
||||
librosa==0.10.1
|
||||
llvmlite==0.42.0
|
||||
Markdown==3.6
|
||||
MarkupSafe==2.1.5
|
||||
matplotlib==3.8.3
|
||||
mojimoji==0.0.13
|
||||
mpmath==1.3.0
|
||||
msgpack==1.0.8
|
||||
multidict==6.0.5
|
||||
murmurhash==1.0.10
|
||||
networkx==2.8.8
|
||||
nltk==3.8.1
|
||||
num2words==0.5.13
|
||||
numba==0.59.1
|
||||
numpy>=1.17.0,<1.29.0
|
||||
nvidia-cublas-cu11>=11.11.3.6
|
||||
nvidia-cudnn-cu11>=9.0.0.312
|
||||
onnxruntime==1.17.1
|
||||
orjson==3.9.15
|
||||
packaging==24.0
|
||||
pandas==1.5.3
|
||||
pillow==10.2.0
|
||||
platformdirs==4.2.0
|
||||
pooch==1.8.1
|
||||
preshed==3.0.9
|
||||
protobuf==5.26.0
|
||||
psutil==5.9.8
|
||||
pycparser==2.21
|
||||
pydantic==2.6.4
|
||||
pydantic_core==2.16.3
|
||||
pydub==0.25.1
|
||||
pynndescent==0.5.11
|
||||
pyparsing==3.1.2
|
||||
pypinyin==0.51.0
|
||||
pyreadline3==3.4.1
|
||||
pysbd==0.3.4
|
||||
python-crfsuite==0.9.10
|
||||
python-dateutil==2.9.0.post0
|
||||
python-Levenshtein>=0.25.0
|
||||
python-multipart==0.0.9
|
||||
pytz==2024.1
|
||||
PyYAML==6.0.1
|
||||
referencing==0.34.0
|
||||
regex==2023.12.25
|
||||
requests==2.31.0
|
||||
rpds-py==0.18.0
|
||||
safetensors==0.4.2
|
||||
scikit-learn==1.4.1.post1
|
||||
scipy==1.12.0
|
||||
semantic-version==2.10.0
|
||||
six==1.16.0
|
||||
smart-open==6.4.0
|
||||
sniffio==1.3.1
|
||||
sounddevice==0.4.6
|
||||
soundfile==0.12.1
|
||||
soxr==0.3.7
|
||||
spacy==3.7.4
|
||||
spacy-legacy==3.0.12
|
||||
spacy-loggers==1.0.5
|
||||
srsly==2.4.8
|
||||
starlette==0.36.3
|
||||
SudachiDict-core==20240109
|
||||
SudachiPy==0.6.8
|
||||
sympy==1.12
|
||||
tensorboard==2.16.2
|
||||
tensorboard-data-server==0.7.2
|
||||
thinc==8.2.3
|
||||
threadpoolctl==3.4.0
|
||||
tokenizers==0.15.2
|
||||
toolz==0.12.1
|
||||
torch>=2.2.0
|
||||
torchaudio>=2.2.0
|
||||
tqdm==4.66.2
|
||||
trainer==0.0.36
|
||||
transformers==4.39.1
|
||||
typer==0.9.4
|
||||
typing_extensions==4.10.0
|
||||
tzdata==2024.1
|
||||
tzlocal==5.2
|
||||
umap-learn==0.5.5
|
||||
Unidecode==1.3.8
|
||||
unidic-lite==1.0.8
|
||||
urllib3==2.2.1
|
||||
uvicorn==0.29.0
|
||||
wasabi==1.1.2
|
||||
weasel==0.3.4
|
||||
websockets==11.0.3
|
||||
Werkzeug==3.0.1
|
||||
yarl==1.9.4
|
||||
zipp==3.18.1
|
||||
@@ -1,172 +0,0 @@
|
||||
absl-py==2.1.0
|
||||
aiofiles==23.2.1
|
||||
aiohttp==3.9.3
|
||||
aiosignal==1.3.1
|
||||
altair==5.2.0
|
||||
annotated-types==0.6.0
|
||||
anyascii==0.3.2
|
||||
anyio==4.3.0
|
||||
attrs==23.2.0
|
||||
audioread==3.0.1
|
||||
av==11.0.0
|
||||
Babel==2.14.0
|
||||
bangla==0.0.2
|
||||
blinker==1.7.0
|
||||
blis==0.7.11
|
||||
bnnumerizer==0.0.2
|
||||
bnunicodenormalizer==0.1.6
|
||||
catalogue==2.0.10
|
||||
certifi==2024.2.2
|
||||
cffi==1.16.0
|
||||
charset-normalizer==3.3.2
|
||||
click==8.1.7
|
||||
cloudpathlib==0.16.0
|
||||
colorama==0.4.6
|
||||
coloredlogs==15.0.1
|
||||
confection==0.1.4
|
||||
contourpy==1.2.0
|
||||
coqpit==0.0.17
|
||||
ctranslate2==4.1.0
|
||||
cutlet==0.4.0
|
||||
cycler==0.12.1
|
||||
cymem==2.0.8
|
||||
Cython==3.0.9
|
||||
dateparser==1.1.8
|
||||
decorator==5.1.1
|
||||
docopt==0.6.2
|
||||
einops==0.7.0
|
||||
encodec==0.1.1
|
||||
fastapi==0.110.0
|
||||
faster-whisper==1.0.1
|
||||
ffmpy==0.3.2
|
||||
filelock==3.13.3
|
||||
Flask==3.0.2
|
||||
flatbuffers==24.3.25
|
||||
fonttools==4.50.0
|
||||
frozenlist==1.4.1
|
||||
fsspec==2024.3.1
|
||||
fugashi==1.3.1
|
||||
fuzzywuzzy>=0.18.0
|
||||
g2pkk==0.1.2
|
||||
gradio==3.50.2
|
||||
gradio_client==0.6.1
|
||||
grpcio==1.62.1
|
||||
gruut==2.2.3
|
||||
gruut-ipa==0.13.0
|
||||
gruut-lang-de==2.0.0
|
||||
gruut-lang-en==2.0.0
|
||||
gruut-lang-es==2.0.0
|
||||
gruut-lang-fr==2.0.2
|
||||
h11==0.14.0
|
||||
hangul-romanize==0.1.0
|
||||
httpcore==1.0.4
|
||||
httpx==0.27.0
|
||||
huggingface-hub==0.22.1
|
||||
humanfriendly==10.0
|
||||
idna==3.6
|
||||
importlib_metadata==7.1.0
|
||||
importlib_resources==6.4.0
|
||||
inflect==7.0.0
|
||||
itsdangerous==2.1.2
|
||||
jaconv==0.3.4
|
||||
jamo==0.4.1
|
||||
jieba==0.42.1
|
||||
Jinja2==3.1.3
|
||||
joblib==1.3.2
|
||||
jsonlines==1.2.0
|
||||
jsonschema==4.21.1
|
||||
jsonschema-specifications==2023.12.1
|
||||
kiwisolver==1.4.5
|
||||
langcodes==3.3.0
|
||||
lazy_loader==0.3
|
||||
librosa==0.10.1
|
||||
llvmlite==0.42.0
|
||||
Markdown==3.6
|
||||
MarkupSafe==2.1.5
|
||||
matplotlib==3.8.3
|
||||
mojimoji==0.0.13
|
||||
mpmath==1.3.0
|
||||
msgpack==1.0.8
|
||||
multidict==6.0.5
|
||||
murmurhash==1.0.10
|
||||
networkx==2.8.8
|
||||
nltk==3.8.1
|
||||
num2words==0.5.13
|
||||
numba==0.59.1
|
||||
numpy==1.26.4
|
||||
nvidia-cublas-cu11>=11.11.3.6
|
||||
nvidia-cudnn-cu11>=9.0.0.312
|
||||
onnxruntime==1.17.1
|
||||
orjson==3.9.15
|
||||
packaging==24.0
|
||||
pandas==1.5.3
|
||||
pillow==10.2.0
|
||||
platformdirs==4.2.0
|
||||
pooch==1.8.1
|
||||
preshed==3.0.9
|
||||
protobuf==5.26.0
|
||||
psutil==5.9.8
|
||||
pycparser==2.21
|
||||
pydantic==2.6.4
|
||||
pydantic_core==2.16.3
|
||||
pydub==0.25.1
|
||||
pynndescent==0.5.11
|
||||
pyparsing==3.1.2
|
||||
pypinyin==0.51.0
|
||||
pyreadline3==3.4.1
|
||||
pysbd==0.3.4
|
||||
python-crfsuite==0.9.10
|
||||
python-dateutil==2.9.0.post0
|
||||
python-Levenshtein>=0.25.0
|
||||
python-multipart==0.0.9
|
||||
pytz==2024.1
|
||||
PyYAML==6.0.1
|
||||
referencing==0.34.0
|
||||
regex==2023.12.25
|
||||
requests==2.31.0
|
||||
rpds-py==0.18.0
|
||||
safetensors==0.4.2
|
||||
scikit-learn==1.4.1.post1
|
||||
scipy==1.12.0
|
||||
semantic-version==2.10.0
|
||||
six==1.16.0
|
||||
smart-open==6.4.0
|
||||
sniffio==1.3.1
|
||||
sounddevice==0.4.6
|
||||
soundfile==0.12.1
|
||||
soxr==0.3.7
|
||||
spacy==3.7.4
|
||||
spacy-legacy==3.0.12
|
||||
spacy-loggers==1.0.5
|
||||
srsly==2.4.8
|
||||
starlette==0.36.3
|
||||
SudachiDict-core==20240109
|
||||
SudachiPy==0.6.8
|
||||
sympy==1.12
|
||||
tensorboard==2.16.2
|
||||
tensorboard-data-server==0.7.2
|
||||
thinc==8.2.3
|
||||
threadpoolctl==3.4.0
|
||||
tokenizers==0.15.2
|
||||
toolz==0.12.1
|
||||
torch>=2.2.0
|
||||
torchaudio>=2.2.0
|
||||
tqdm==4.66.2
|
||||
trainer==0.0.36
|
||||
transformers==4.39.1
|
||||
TTS==0.22.0
|
||||
typer==0.9.4
|
||||
typing_extensions==4.10.0
|
||||
tzdata==2024.1
|
||||
tzlocal==5.2
|
||||
umap-learn==0.5.5
|
||||
Unidecode==1.3.8
|
||||
unidic-lite==1.0.8
|
||||
urllib3==2.2.1
|
||||
uvicorn==0.29.0
|
||||
wasabi==1.1.2
|
||||
weasel==0.3.4
|
||||
websockets==11.0.3
|
||||
Werkzeug==3.0.1
|
||||
yarl==1.9.4
|
||||
zipp==3.18.1
|
||||
@@ -1,24 +0,0 @@
|
||||
numpy>=1.22.0
|
||||
soundfile>=0.12.1
|
||||
uvicorn>=0.24.0.post1
|
||||
transformers>=4.37.1
|
||||
TTS>=0.22.0
|
||||
torch>=2.1.0+cu118
|
||||
torchaudio>=2.1.0+cu118
|
||||
fastapi>=0.104.1
|
||||
Jinja2>=3.1.2
|
||||
requests>=2.31.0
|
||||
tqdm>=4.66.1
|
||||
importlib-metadata>=4.8.1
|
||||
packaging>=23.2
|
||||
pydantic>=1.10.13
|
||||
sounddevice>=0.4.6
|
||||
python-multipart>=0.0.6
|
||||
cutlet>=0.3.0
|
||||
unidic-lite>=1.0.8
|
||||
faster-whisper>=0.10.0
|
||||
pandas>=1.5.0
|
||||
nvidia-cublas-cu11>=11.11.3.6
|
||||
nvidia-cudnn-cu11>=9.0.0.312
|
||||
fuzzywuzzy>=0.18.0
|
||||
python-Levenshtein>=0.25.0
|
||||
@@ -1,833 +0,0 @@
|
||||
import { doExtrasFetch, getApiUrl, modules } from '../../extensions.js';
|
||||
import { saveTtsProviderSettings } from './index.js';
|
||||
|
||||
export { AllTalkTtsProvider };
|
||||
|
||||
class AllTalkTtsProvider {
|
||||
//########//
|
||||
// Config //
|
||||
//########//
|
||||
|
||||
settings = {};
|
||||
constructor() {
|
||||
// Initialize with default settings if they are not already set
|
||||
this.settings = {
|
||||
provider_endpoint: this.settings.provider_endpoint || 'http://localhost:7851',
|
||||
language: this.settings.language || 'en',
|
||||
voiceMap: this.settings.voiceMap || {},
|
||||
at_generation_method: this.settings.at_generation_method || 'standard_generation',
|
||||
narrator_enabled: this.settings.narrator_enabled || 'false',
|
||||
at_narrator_text_not_inside: this.settings.at_narrator_text_not_inside || 'narrator',
|
||||
narrator_voice_gen: this.settings.narrator_voice_gen || 'female_01.wav',
|
||||
finetuned_model: this.settings.finetuned_model || 'false'
|
||||
};
|
||||
// Separate property for dynamically updated settings from the server
|
||||
this.dynamicSettings = {
|
||||
modelsAvailable: [],
|
||||
currentModel: '',
|
||||
deepspeed_available: false,
|
||||
deepSpeedEnabled: false,
|
||||
lowVramEnabled: false,
|
||||
};
|
||||
}
|
||||
ready = false;
|
||||
voices = [];
|
||||
separator = '. ';
|
||||
audioElement = document.createElement('audio');
|
||||
|
||||
languageLabels = {
|
||||
'Arabic': 'ar',
|
||||
'Brazilian Portuguese': 'pt',
|
||||
'Chinese': 'zh-cn',
|
||||
'Czech': 'cs',
|
||||
'Dutch': 'nl',
|
||||
'English': 'en',
|
||||
'French': 'fr',
|
||||
'German': 'de',
|
||||
'Italian': 'it',
|
||||
'Polish': 'pl',
|
||||
'Russian': 'ru',
|
||||
'Spanish': 'es',
|
||||
'Turkish': 'tr',
|
||||
'Japanese': 'ja',
|
||||
'Korean': 'ko',
|
||||
'Hungarian': 'hu',
|
||||
'Hindi': 'hi',
|
||||
};
|
||||
|
||||
get settingsHtml() {
|
||||
let html = `<div class="at-settings-separator">AllTalk Settings</div>`;
|
||||
|
||||
html += `<div class="at-settings-row">
|
||||
|
||||
<div class="at-settings-option">
|
||||
<label for="at_generation_method">AllTalk TTS Generation Method</label>
|
||||
<select id="at_generation_method">
|
||||
<option value="standard_generation">Standard Audio Generation (AT Narrator - Optional)</option>
|
||||
<option value="streaming_enabled">Streaming Audio Generation (AT Narrator - Disabled)</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>`;
|
||||
|
||||
html += `<div class="at-settings-row">
|
||||
|
||||
<div class="at-settings-option">
|
||||
<label for="at_narrator_enabled">AT Narrator</label>
|
||||
<select id="at_narrator_enabled">
|
||||
<option value="true">Enabled</option>
|
||||
<option value="false">Disabled</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="at-settings-option">
|
||||
<label for="at_narrator_text_not_inside">Text Not Inside * or " is</label>
|
||||
<select id="at_narrator_text_not_inside">
|
||||
<option value="narrator">Narrator</option>
|
||||
<option value="character">Character</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
</div>`;
|
||||
|
||||
html += `<div class="at-settings-row">
|
||||
<div class="at-settings-option">
|
||||
<label for="narrator_voice">Narrator Voice</label>
|
||||
<select id="narrator_voice">`;
|
||||
if (this.voices) {
|
||||
for (let voice of this.voices) {
|
||||
html += `<option value="${voice.voice_id}">${voice.name}</option>`;
|
||||
}
|
||||
}
|
||||
html += `</select>
|
||||
</div>
|
||||
<div class="at-settings-option">
|
||||
<label for="language_options">Language</label>
|
||||
<select id="language_options">`;
|
||||
for (let language in this.languageLabels) {
|
||||
html += `<option value="${this.languageLabels[language]}" ${this.languageLabels[language] === this.settings?.language ? 'selected="selected"' : ''}>${language}</option>`;
|
||||
}
|
||||
html += `</select>
|
||||
</div>
|
||||
</div>`;
|
||||
|
||||
|
||||
html += `<div class="at-model-endpoint-row">
|
||||
<div class="at-model-option">
|
||||
<label for="switch_model">Switch Model</label>
|
||||
<select id="switch_model">
|
||||
<option value="api_tts">API TTS</option>
|
||||
<option value="api_local">API Local</option>
|
||||
<option value="xttsv2_local">XTTSv2 Local</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="at-endpoint-option">
|
||||
<label for="at_server">AllTalk Endpoint:</label>
|
||||
<input id="at_server" type="text" class="text_pole" maxlength="80" value="${this.settings.provider_endpoint}"/>
|
||||
</div>
|
||||
</div>`;
|
||||
|
||||
|
||||
html += `<div class="at-model-endpoint-row">
|
||||
<div class="at-settings-option">
|
||||
<label for="low_vram">Low VRAM</label>
|
||||
<input id="low_vram" type="checkbox"/>
|
||||
</div>
|
||||
<div class="at-settings-option">
|
||||
<label for="deepspeed">DeepSpeed</label>
|
||||
<input id="deepspeed" type="checkbox"/>
|
||||
</div>
|
||||
<div class="at-settings-option status-option">
|
||||
<span>Status: <span id="status_info">Ready</span></span>
|
||||
</div>
|
||||
<div class="at-settings-option empty-option">
|
||||
<!-- This div remains empty for spacing -->
|
||||
</div>
|
||||
</div>`;
|
||||
|
||||
|
||||
html += `<div class="at-website-row">
|
||||
<div class="at-website-option">
|
||||
<span>AllTalk <a target="_blank" href="${this.settings.provider_endpoint}">Config & Docs</a>.</span>
|
||||
</div>
|
||||
|
||||
<div class="at-website-option">
|
||||
<span>AllTalk <a target="_blank" href="https://github.com/erew123/alltalk_tts/">Website</a>.</span>
|
||||
</div>
|
||||
</div>`;
|
||||
|
||||
html += `<div class="at-website-row">
|
||||
<div class="at-website-option">
|
||||
<span><strong>Text-generation-webui</strong> users - Uncheck <strong>Enable TTS</strong> in Text-generation-webui.</span>
|
||||
</div>
|
||||
</div>`;
|
||||
|
||||
return html;
|
||||
}
|
||||
|
||||
|
||||
//#################//
|
||||
// Startup ST & AT //
|
||||
//#################//
|
||||
|
||||
async loadSettings(settings) {
|
||||
updateStatus('Offline');
|
||||
|
||||
if (Object.keys(settings).length === 0) {
|
||||
console.info('Using default AllTalk TTS Provider settings');
|
||||
} else {
|
||||
// Populate settings with provided values, ignoring server-provided settings
|
||||
for (const key in settings) {
|
||||
if (key in this.settings) {
|
||||
this.settings[key] = settings[key];
|
||||
} else {
|
||||
console.debug(`Ignoring non-user-configurable setting: ${key}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update UI elements to reflect the loaded settings
|
||||
$('#at_server').val(this.settings.provider_endpoint);
|
||||
$('#language_options').val(this.settings.language);
|
||||
//$('#voicemap').val(this.settings.voiceMap);
|
||||
$('#at_generation_method').val(this.settings.at_generation_method);
|
||||
$('#at_narrator_enabled').val(this.settings.narrator_enabled);
|
||||
$('#at_narrator_text_not_inside').val(this.settings.at_narrator_text_not_inside);
|
||||
$('#narrator_voice').val(this.settings.narrator_voice_gen);
|
||||
|
||||
console.debug('AllTalkTTS: Settings loaded');
|
||||
try {
|
||||
// Check if TTS provider is ready
|
||||
await this.checkReady();
|
||||
await this.updateSettingsFromServer(); // Fetch dynamic settings from the TTS server
|
||||
await this.fetchTtsVoiceObjects(); // Fetch voices only if service is ready
|
||||
this.updateNarratorVoicesDropdown();
|
||||
this.updateLanguageDropdown();
|
||||
this.setupEventListeners();
|
||||
this.applySettingsToHTML();
|
||||
updateStatus('Ready');
|
||||
} catch (error) {
|
||||
console.error("Error loading settings:", error);
|
||||
updateStatus('Offline');
|
||||
}
|
||||
}
|
||||
|
||||
applySettingsToHTML() {
|
||||
// Apply loaded settings or use defaults
|
||||
const narratorVoiceSelect = document.getElementById('narrator_voice');
|
||||
const atNarratorSelect = document.getElementById('at_narrator_enabled');
|
||||
const textNotInsideSelect = document.getElementById('at_narrator_text_not_inside');
|
||||
const generationMethodSelect = document.getElementById('at_generation_method');
|
||||
this.settings.narrator_voice = this.settings.narrator_voice_gen;
|
||||
// Apply settings to Narrator Voice dropdown
|
||||
if (narratorVoiceSelect && this.settings.narrator_voice) {
|
||||
narratorVoiceSelect.value = this.settings.narrator_voice.replace('.wav', '');
|
||||
}
|
||||
// Apply settings to AT Narrator Enabled dropdown
|
||||
if (atNarratorSelect) {
|
||||
// Sync the state with the checkbox in index.js
|
||||
const ttsPassAsterisksCheckbox = document.getElementById('tts_pass_asterisks'); // Access the checkbox from index.js
|
||||
const ttsNarrateQuotedCheckbox = document.getElementById('tts_narrate_quoted'); // Access the checkbox from index.js
|
||||
const ttsNarrateDialoguesCheckbox = document.getElementById('tts_narrate_dialogues'); // Access the checkbox from index.js
|
||||
// Sync the state with the checkbox in index.js
|
||||
if (this.settings.narrator_enabled) {
|
||||
ttsPassAsterisksCheckbox.checked = false;
|
||||
$('#tts_pass_asterisks').click(); // Simulate a click event
|
||||
$('#tts_pass_asterisks').trigger('change');
|
||||
}
|
||||
if (!this.settings.narrator_enabled) {
|
||||
ttsPassAsterisksCheckbox.checked = true;
|
||||
$('#tts_pass_asterisks').click(); // Simulate a click event
|
||||
$('#tts_pass_asterisks').trigger('change');
|
||||
}
|
||||
// Uncheck and set tts_narrate_quoted to false if narrator is enabled
|
||||
if (this.settings.narrator_enabledd) {
|
||||
ttsNarrateQuotedCheckbox.checked = true;
|
||||
ttsNarrateDialoguesCheckbox.checked = true;
|
||||
// Trigger click events instead of change events
|
||||
$('#tts_narrate_quoted').click();
|
||||
$('#tts_narrate_quoted').trigger('change');
|
||||
$('#tts_narrate_dialogues').click();
|
||||
$('#tts_narrate_dialogues').trigger('change');
|
||||
}
|
||||
atNarratorSelect.value = this.settings.narrator_enabled.toString();
|
||||
this.settings.narrator_enabled = this.settings.narrator_enabled.toString();
|
||||
}
|
||||
// Apply settings to the Language dropdown
|
||||
const languageSelect = document.getElementById('language_options');
|
||||
if (languageSelect && this.settings.language) {
|
||||
languageSelect.value = this.settings.language;
|
||||
}
|
||||
// Apply settings to Text Not Inside dropdown
|
||||
if (textNotInsideSelect && this.settings.text_not_inside) {
|
||||
textNotInsideSelect.value = this.settings.text_not_inside;
|
||||
this.settings.at_narrator_text_not_inside = this.settings.text_not_inside;
|
||||
}
|
||||
// Apply settings to Generation Method dropdown
|
||||
if (generationMethodSelect && this.settings.at_generation_method) {
|
||||
generationMethodSelect.value = this.settings.at_generation_method;
|
||||
}
|
||||
// Additional logic to disable/enable dropdowns based on the selected generation method
|
||||
const isStreamingEnabled = this.settings.at_generation_method === 'streaming_enabled';
|
||||
if (isStreamingEnabled) {
|
||||
// Disable certain dropdowns when streaming is enabled
|
||||
if (atNarratorSelect) atNarratorSelect.disabled = true;
|
||||
if (textNotInsideSelect) textNotInsideSelect.disabled = true;
|
||||
if (narratorVoiceSelect) narratorVoiceSelect.disabled = true;
|
||||
} else {
|
||||
// Enable dropdowns for standard generation
|
||||
if (atNarratorSelect) atNarratorSelect.disabled = false;
|
||||
if (textNotInsideSelect) textNotInsideSelect.disabled = !this.settings.narrator_enabled;
|
||||
if (narratorVoiceSelect) narratorVoiceSelect.disabled = !this.settings.narrator_enabled;
|
||||
}
|
||||
const modelSelect = document.getElementById('switch_model');
|
||||
if (this.settings.finetuned_model === 'true') {
|
||||
const ftOption = document.createElement('option');
|
||||
ftOption.value = 'XTTSv2 FT';
|
||||
ftOption.textContent = 'XTTSv2 FT';
|
||||
modelSelect.appendChild(ftOption);
|
||||
}
|
||||
}
|
||||
|
||||
//##############################//
|
||||
// Check AT Server is Available //
|
||||
//##############################//
|
||||
|
||||
async checkReady() {
|
||||
try {
|
||||
const response = await fetch(`${this.settings.provider_endpoint}/api/ready`);
|
||||
// Check if the HTTP request was successful
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP Error Response: ${response.status} ${response.statusText}`);
|
||||
}
|
||||
const statusText = await response.text();
|
||||
// Check if the response is 'Ready'
|
||||
if (statusText === 'Ready') {
|
||||
this.ready = true; // Set the ready flag to true
|
||||
console.log('TTS service is ready.');
|
||||
} else {
|
||||
this.ready = false;
|
||||
console.log('TTS service is not ready.');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error checking TTS service readiness:', error);
|
||||
this.ready = false; // Ensure ready flag is set to false in case of error
|
||||
}
|
||||
}
|
||||
|
||||
//######################//
|
||||
// Get Available Voices //
|
||||
//######################//
|
||||
|
||||
async fetchTtsVoiceObjects() {
|
||||
const response = await fetch(`${this.settings.provider_endpoint}/api/voices`);
|
||||
if (!response.ok) {
|
||||
const errorText = await response.text();
|
||||
throw new Error(`HTTP ${response.status}: ${errorText}`);
|
||||
}
|
||||
const data = await response.json();
|
||||
const voices = data.voices.map(filename => {
|
||||
const voiceName = filename.replace('.wav', '');
|
||||
return {
|
||||
name: voiceName,
|
||||
voice_id: voiceName,
|
||||
preview_url: null, // Preview URL will be dynamically generated
|
||||
lang: 'en' // Default language
|
||||
};
|
||||
});
|
||||
this.voices = voices; // Assign to the class property
|
||||
return voices; // Also return this list
|
||||
}
|
||||
|
||||
//##########################################//
|
||||
// Get Current AT Server Config & Update ST //
|
||||
//##########################################//
|
||||
|
||||
async updateSettingsFromServer() {
|
||||
try {
|
||||
// Fetch current settings
|
||||
const response = await fetch(`${this.settings.provider_endpoint}/api/currentsettings`);
|
||||
if (!response.ok) {
|
||||
throw new Error(`Failed to fetch current settings: ${response.statusText}`);
|
||||
}
|
||||
const currentSettings = await response.json();
|
||||
// Update internal settings
|
||||
this.settings.modelsAvailable = currentSettings.models_available;
|
||||
this.settings.currentModel = currentSettings.current_model_loaded;
|
||||
this.settings.deepspeed_available = currentSettings.deepspeed_available;
|
||||
this.settings.deepSpeedEnabled = currentSettings.deepspeed_status;
|
||||
this.settings.lowVramEnabled = currentSettings.low_vram_status;
|
||||
this.settings.finetuned_model = currentSettings.finetuned_model
|
||||
// Update HTML elements
|
||||
this.updateModelDropdown();
|
||||
this.updateCheckboxes();
|
||||
} catch (error) {
|
||||
console.error(`Error updating settings from server: ${error}`);
|
||||
}
|
||||
}
|
||||
|
||||
//###################################################//
|
||||
// Get Current AT Server Config & Update ST (Models) //
|
||||
//###################################################//
|
||||
|
||||
updateModelDropdown() {
|
||||
const modelSelect = document.getElementById('switch_model');
|
||||
if (modelSelect) {
|
||||
modelSelect.innerHTML = ''; // Clear existing options
|
||||
this.settings.modelsAvailable.forEach(model => {
|
||||
const option = document.createElement('option');
|
||||
option.value = model.model_name;
|
||||
option.textContent = model.model_name; // Use model_name instead of name
|
||||
option.selected = model.model_name === this.settings.currentModel;
|
||||
modelSelect.appendChild(option);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
//#######################################################//
|
||||
// Get Current AT Server Config & Update ST (DS and LVR) //
|
||||
//#######################################################//
|
||||
|
||||
updateCheckboxes() {
|
||||
const deepspeedCheckbox = document.getElementById('deepspeed');
|
||||
const lowVramCheckbox = document.getElementById('low_vram');
|
||||
if (lowVramCheckbox) lowVramCheckbox.checked = this.settings.lowVramEnabled;
|
||||
if (deepspeedCheckbox) {
|
||||
deepspeedCheckbox.checked = this.settings.deepSpeedEnabled;
|
||||
deepspeedCheckbox.disabled = !this.settings.deepspeed_available; // Disable checkbox if deepspeed is not available
|
||||
}
|
||||
}
|
||||
|
||||
//###############################################################//
|
||||
// Get Current AT Server Config & Update ST (AT Narrator Voices) //
|
||||
//###############################################################//
|
||||
|
||||
updateNarratorVoicesDropdown() {
|
||||
const narratorVoiceSelect = document.getElementById('narrator_voice');
|
||||
if (narratorVoiceSelect && this.voices) {
|
||||
// Clear existing options
|
||||
narratorVoiceSelect.innerHTML = '';
|
||||
// Add new options
|
||||
for (let voice of this.voices) {
|
||||
const option = document.createElement('option');
|
||||
option.value = voice.voice_id;
|
||||
option.textContent = voice.name;
|
||||
narratorVoiceSelect.appendChild(option);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//######################################################//
|
||||
// Get Current AT Server Config & Update ST (Languages) //
|
||||
//######################################################//
|
||||
|
||||
updateLanguageDropdown() {
|
||||
const languageSelect = document.getElementById('language_options');
|
||||
if (languageSelect) {
|
||||
// Ensure default language is set
|
||||
this.settings.language = this.settings.language;
|
||||
|
||||
languageSelect.innerHTML = '';
|
||||
for (let language in this.languageLabels) {
|
||||
const option = document.createElement('option');
|
||||
option.value = this.languageLabels[language];
|
||||
option.textContent = language;
|
||||
if (this.languageLabels[language] === this.settings.language) {
|
||||
option.selected = true;
|
||||
}
|
||||
languageSelect.appendChild(option);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//########################################//
|
||||
// Start AT TTS extenstion page listeners //
|
||||
//########################################//
|
||||
|
||||
setupEventListeners() {
|
||||
|
||||
let debounceTimeout;
|
||||
const debounceDelay = 500; // Milliseconds
|
||||
|
||||
// Define the event handler function
|
||||
const onModelSelectChange = async (event) => {
|
||||
console.log("Model select change event triggered"); // Debugging statement
|
||||
const selectedModel = event.target.value;
|
||||
console.log(`Selected model: ${selectedModel}`); // Debugging statement
|
||||
// Set status to Processing
|
||||
updateStatus('Processing');
|
||||
try {
|
||||
const response = await fetch(`${this.settings.provider_endpoint}/api/reload?tts_method=${encodeURIComponent(selectedModel)}`, {
|
||||
method: 'POST'
|
||||
});
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP Error: ${response.status}`);
|
||||
}
|
||||
const data = await response.json();
|
||||
console.log("POST response data:", data); // Debugging statement
|
||||
// Set status to Ready if successful
|
||||
updateStatus('Ready');
|
||||
} catch (error) {
|
||||
console.error("POST request error:", error); // Debugging statement
|
||||
// Set status to Error in case of failure
|
||||
updateStatus('Error');
|
||||
}
|
||||
|
||||
// Handle response or error
|
||||
};
|
||||
|
||||
const debouncedModelSelectChange = (event) => {
|
||||
clearTimeout(debounceTimeout);
|
||||
debounceTimeout = setTimeout(() => {
|
||||
onModelSelectChange(event);
|
||||
}, debounceDelay);
|
||||
};
|
||||
|
||||
// Switch Model Listener
|
||||
const modelSelect = document.getElementById('switch_model');
|
||||
if (modelSelect) {
|
||||
// Remove the event listener if it was previously added
|
||||
modelSelect.removeEventListener('change', debouncedModelSelectChange);
|
||||
// Add the debounced event listener
|
||||
modelSelect.addEventListener('change', debouncedModelSelectChange);
|
||||
}
|
||||
|
||||
// DeepSpeed Listener
|
||||
const deepspeedCheckbox = document.getElementById('deepspeed');
|
||||
if (deepspeedCheckbox) {
|
||||
deepspeedCheckbox.addEventListener('change', async (event) => {
|
||||
const deepSpeedValue = event.target.checked ? 'True' : 'False';
|
||||
// Set status to Processing
|
||||
updateStatus('Processing');
|
||||
try {
|
||||
const response = await fetch(`${this.settings.provider_endpoint}/api/deepspeed?new_deepspeed_value=${deepSpeedValue}`, {
|
||||
method: 'POST'
|
||||
});
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP Error: ${response.status}`);
|
||||
}
|
||||
const data = await response.json();
|
||||
console.log("POST response data:", data); // Debugging statement
|
||||
// Set status to Ready if successful
|
||||
updateStatus('Ready');
|
||||
} catch (error) {
|
||||
console.error("POST request error:", error); // Debugging statement
|
||||
// Set status to Error in case of failure
|
||||
updateStatus('Error');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Low VRAM Listener
|
||||
const lowVramCheckbox = document.getElementById('low_vram');
|
||||
if (lowVramCheckbox) {
|
||||
lowVramCheckbox.addEventListener('change', async (event) => {
|
||||
const lowVramValue = event.target.checked ? 'True' : 'False';
|
||||
// Set status to Processing
|
||||
updateStatus('Processing');
|
||||
try {
|
||||
const response = await fetch(`${this.settings.provider_endpoint}/api/lowvramsetting?new_low_vram_value=${lowVramValue}`, {
|
||||
method: 'POST'
|
||||
});
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP Error: ${response.status}`);
|
||||
}
|
||||
const data = await response.json();
|
||||
console.log("POST response data:", data); // Debugging statement
|
||||
// Set status to Ready if successful
|
||||
updateStatus('Ready');
|
||||
} catch (error) {
|
||||
console.error("POST request error:", error); // Debugging statement
|
||||
// Set status to Error in case of failure
|
||||
updateStatus('Error');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Narrator Voice Dropdown Listener
|
||||
const narratorVoiceSelect = document.getElementById('narrator_voice');
|
||||
if (narratorVoiceSelect) {
|
||||
narratorVoiceSelect.addEventListener('change', (event) => {
|
||||
this.settings.narrator_voice_gen = `${event.target.value}.wav`;
|
||||
this.onSettingsChange(); // Save the settings after change
|
||||
});
|
||||
}
|
||||
|
||||
const textNotInsideSelect = document.getElementById('at_narrator_text_not_inside');
|
||||
if (textNotInsideSelect) {
|
||||
textNotInsideSelect.addEventListener('change', (event) => {
|
||||
this.settings.text_not_inside = event.target.value;
|
||||
this.onSettingsChange(); // Save the settings after change
|
||||
});
|
||||
}
|
||||
|
||||
// AT Narrator Dropdown Listener
|
||||
const atNarratorSelect = document.getElementById('at_narrator_enabled');
|
||||
const ttsPassAsterisksCheckbox = document.getElementById('tts_pass_asterisks'); // Access the checkbox from index.js
|
||||
const ttsNarrateQuotedCheckbox = document.getElementById('tts_narrate_quoted'); // Access the checkbox from index.js
|
||||
const ttsNarrateDialoguesCheckbox = document.getElementById('tts_narrate_dialogues'); // Access the checkbox from index.js
|
||||
|
||||
if (atNarratorSelect && textNotInsideSelect && narratorVoiceSelect) {
|
||||
atNarratorSelect.addEventListener('change', (event) => {
|
||||
const isNarratorEnabled = event.target.value === 'true';
|
||||
this.settings.narrator_enabled = isNarratorEnabled; // Update the setting here
|
||||
textNotInsideSelect.disabled = !isNarratorEnabled;
|
||||
narratorVoiceSelect.disabled = !isNarratorEnabled;
|
||||
|
||||
// Sync the state with the checkbox in index.js
|
||||
if (isNarratorEnabled) {
|
||||
ttsPassAsterisksCheckbox.checked = false;
|
||||
$('#tts_pass_asterisks').click(); // Simulate a click event
|
||||
$('#tts_pass_asterisks').trigger('change');
|
||||
}
|
||||
if (!isNarratorEnabled) {
|
||||
ttsPassAsterisksCheckbox.checked = true;
|
||||
$('#tts_pass_asterisks').click(); // Simulate a click event
|
||||
$('#tts_pass_asterisks').trigger('change');
|
||||
}
|
||||
// Uncheck and set tts_narrate_quoted to false if narrator is enabled
|
||||
if (isNarratorEnabled) {
|
||||
ttsNarrateQuotedCheckbox.checked = true;
|
||||
ttsNarrateDialoguesCheckbox.checked = true;
|
||||
// Trigger click events instead of change events
|
||||
$('#tts_narrate_quoted').click();
|
||||
$('#tts_narrate_quoted').trigger('change');
|
||||
$('#tts_narrate_dialogues').click();
|
||||
$('#tts_narrate_dialogues').trigger('change');
|
||||
}
|
||||
this.onSettingsChange(); // Save the settings after change
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// Event Listener for AT Generation Method Dropdown
|
||||
const atGenerationMethodSelect = document.getElementById('at_generation_method');
|
||||
const atNarratorEnabledSelect = document.getElementById('at_narrator_enabled');
|
||||
if (atGenerationMethodSelect) {
|
||||
atGenerationMethodSelect.addEventListener('change', (event) => {
|
||||
const selectedMethod = event.target.value;
|
||||
|
||||
if (selectedMethod === 'streaming_enabled') {
|
||||
// Disable and unselect AT Narrator
|
||||
atNarratorEnabledSelect.disabled = true;
|
||||
atNarratorEnabledSelect.value = 'false';
|
||||
textNotInsideSelect.disabled = true;
|
||||
narratorVoiceSelect.disabled = true;
|
||||
} else if (selectedMethod === 'standard_generation') {
|
||||
// Enable AT Narrator
|
||||
atNarratorEnabledSelect.disabled = false;
|
||||
}
|
||||
this.settings.at_generation_method = selectedMethod; // Update the setting here
|
||||
this.onSettingsChange(); // Save the settings after change
|
||||
});
|
||||
}
|
||||
|
||||
// Listener for Language Dropdown
|
||||
const languageSelect = document.getElementById('language_options');
|
||||
if (languageSelect) {
|
||||
languageSelect.addEventListener('change', (event) => {
|
||||
this.settings.language = event.target.value;
|
||||
this.onSettingsChange(); // Save the settings after change
|
||||
});
|
||||
}
|
||||
|
||||
// Listener for AllTalk Endpoint Input
|
||||
const atServerInput = document.getElementById('at_server');
|
||||
if (atServerInput) {
|
||||
atServerInput.addEventListener('input', (event) => {
|
||||
this.settings.provider_endpoint = event.target.value;
|
||||
this.onSettingsChange(); // Save the settings after change
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//#############################//
|
||||
// Store ST interface settings //
|
||||
//#############################//
|
||||
|
||||
onSettingsChange() {
|
||||
// Update settings based on the UI elements
|
||||
//this.settings.provider_endpoint = $('#at_server').val();
|
||||
this.settings.language = $('#language_options').val();
|
||||
//this.settings.voiceMap = $('#voicemap').val();
|
||||
this.settings.at_generation_method = $('#at_generation_method').val();
|
||||
this.settings.narrator_enabled = $('#at_narrator_enabled').val();
|
||||
this.settings.at_narrator_text_not_inside = $('#at_narrator_text_not_inside').val();
|
||||
this.settings.narrator_voice_gen = $('#narrator_voice').val();
|
||||
// Save the updated settings
|
||||
saveTtsProviderSettings();
|
||||
}
|
||||
|
||||
//#########################//
|
||||
// ST Handle Reload button //
|
||||
//#########################//
|
||||
|
||||
async onRefreshClick() {
|
||||
await this.checkReady(); // Check if the TTS provider is ready
|
||||
await this.loadSettings(this.settings); // Reload the settings
|
||||
// Additional actions as needed
|
||||
}
|
||||
|
||||
//##################//
|
||||
// Preview AT Voice //
|
||||
//##################//
|
||||
|
||||
async previewTtsVoice(voiceName) {
|
||||
try {
|
||||
// Prepare data for POST request
|
||||
const postData = new URLSearchParams();
|
||||
postData.append("voice", `${voiceName}.wav`);
|
||||
// Making the POST request
|
||||
const response = await fetch(`${this.settings.provider_endpoint}/api/previewvoice/`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded'
|
||||
},
|
||||
body: postData,
|
||||
});
|
||||
if (!response.ok) {
|
||||
const errorText = await response.text();
|
||||
console.error(`[previewTtsVoice] Error Response Text:`, errorText);
|
||||
throw new Error(`HTTP ${response.status}: ${errorText}`);
|
||||
}
|
||||
// Assuming the server returns a URL to the .wav file
|
||||
const data = await response.json();
|
||||
if (data.output_file_url) {
|
||||
// Use an audio element to play the .wav file
|
||||
const audioElement = new Audio(data.output_file_url);
|
||||
audioElement.play().catch(e => console.error("Error playing audio:", e));
|
||||
} else {
|
||||
console.warn("[previewTtsVoice] No output file URL received in the response");
|
||||
throw new Error("No output file URL received in the response");
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error("[previewTtsVoice] Exception caught during preview generation:", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
//#####################//
|
||||
// Populate ST voices //
|
||||
//#####################//
|
||||
|
||||
async getVoice(voiceName, generatePreview = false) {
|
||||
// Ensure this.voices is populated
|
||||
if (this.voices.length === 0) {
|
||||
// Fetch voice objects logic
|
||||
}
|
||||
// Find the object where the name matches voiceName
|
||||
const match = this.voices.find(voice => voice.name === voiceName);
|
||||
if (!match) {
|
||||
// Error handling
|
||||
}
|
||||
// Generate preview URL only if requested
|
||||
if (!match.preview_url && generatePreview) {
|
||||
// Generate preview logic
|
||||
}
|
||||
return match; // Return the found voice object
|
||||
}
|
||||
|
||||
//##########################################//
|
||||
// Generate TTS Streaming or call Standard //
|
||||
//##########################################//
|
||||
|
||||
async generateTts(inputText, voiceId) {
|
||||
try {
|
||||
if (this.settings.at_generation_method === 'streaming_enabled') {
|
||||
// Construct the streaming URL
|
||||
const streamingUrl = `${this.settings.provider_endpoint}/api/tts-generate-streaming?text=${encodeURIComponent(inputText)}&voice=${encodeURIComponent(voiceId)}.wav&language=${encodeURIComponent(this.settings.language)}&output_file=stream_output.wav`;
|
||||
console.log("Streaming URL:", streamingUrl);
|
||||
|
||||
// Return the streaming URL directly
|
||||
return streamingUrl;
|
||||
} else {
|
||||
// For standard method
|
||||
const outputUrl = await this.fetchTtsGeneration(inputText, voiceId);
|
||||
const audioResponse = await fetch(outputUrl);
|
||||
if (!audioResponse.ok) {
|
||||
throw new Error(`HTTP ${audioResponse.status}: Failed to fetch audio data`);
|
||||
}
|
||||
return audioResponse; // Return the fetch response directly
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error in generateTts:", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//####################//
|
||||
// Generate Standard //
|
||||
//####################//
|
||||
|
||||
async fetchTtsGeneration(inputText, voiceId) {
|
||||
// Prepare the request payload
|
||||
const requestBody = new URLSearchParams({
|
||||
'text_input': inputText,
|
||||
'text_filtering': "standard",
|
||||
'character_voice_gen': voiceId + ".wav",
|
||||
'narrator_enabled': this.settings.narrator_enabled,
|
||||
'narrator_voice_gen': this.settings.narrator_voice_gen + ".wav",
|
||||
'text_not_inside': this.settings.at_narrator_text_not_inside,
|
||||
'language': this.settings.language,
|
||||
'output_file_name': "st_output",
|
||||
'output_file_timestamp': "true",
|
||||
'autoplay': "false",
|
||||
'autoplay_volume': "0.8"
|
||||
}).toString();
|
||||
|
||||
try {
|
||||
const response = await doExtrasFetch(
|
||||
`${this.settings.provider_endpoint}/api/tts-generate`,
|
||||
{
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
'Cache-Control': 'no-cache',
|
||||
},
|
||||
body: requestBody
|
||||
}
|
||||
);
|
||||
|
||||
if (!response.ok) {
|
||||
const errorText = await response.text();
|
||||
console.error(`[fetchTtsGeneration] Error Response Text:`, errorText);
|
||||
// toastr.error(response.statusText, 'TTS Generation Failed');
|
||||
throw new Error(`HTTP ${response.status}: ${errorText}`);
|
||||
}
|
||||
const data = await response.json();
|
||||
const outputUrl = data.output_file_url;
|
||||
return outputUrl; // Return only the output_file_url
|
||||
} catch (error) {
|
||||
console.error("[fetchTtsGeneration] Exception caught:", error);
|
||||
throw error; // Rethrow the error for further handling
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//#########################//
|
||||
// Update Status Messages //
|
||||
//#########################//
|
||||
|
||||
function updateStatus(message) {
|
||||
const statusElement = document.getElementById('status_info');
|
||||
if (statusElement) {
|
||||
statusElement.textContent = message;
|
||||
switch (message) {
|
||||
case 'Offline':
|
||||
statusElement.style.color = 'red';
|
||||
break;
|
||||
case 'Ready':
|
||||
statusElement.style.color = 'lightgreen';
|
||||
break;
|
||||
case 'Processing':
|
||||
statusElement.style.color = 'blue';
|
||||
break;
|
||||
case 'Error':
|
||||
statusElement.style.color = 'red';
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,159 +0,0 @@
|
||||
#tts_media_control {
|
||||
/* order: 100; */
|
||||
/* width: 40px;
|
||||
height: 40px;
|
||||
margin: 0;
|
||||
padding: 1px; */
|
||||
outline: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
/* transition: 0.3s;
|
||||
opacity: 0.7; */
|
||||
display: flex;
|
||||
align-items: center;
|
||||
/* justify-content: center; */
|
||||
|
||||
}
|
||||
|
||||
#ttsExtensionMenuItem {
|
||||
transition: 0.3s;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
#ttsExtensionMenuItem:hover {
|
||||
opacity: 1;
|
||||
filter: brightness(1.2);
|
||||
}
|
||||
|
||||
#tts_media_control:hover {
|
||||
opacity: 1;
|
||||
filter: brightness(1.2);
|
||||
}
|
||||
|
||||
.voice_preview {
|
||||
margin: 0.25rem 0.5rem;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.voice_preview .voice_name {
|
||||
text-align: left;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.voice_preview .voice_lang {
|
||||
width: 4rem;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.voice_preview .fa-play {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.tts-button {
|
||||
margin: 0;
|
||||
outline: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
transition: 0.3s;
|
||||
opacity: 0.7;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
}
|
||||
|
||||
.tts-button:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.tts_block {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
column-gap: 5px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.tts_custom_voices {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
gap: 5px;
|
||||
}
|
||||
|
||||
.novel_tts_hints {
|
||||
font-size: calc(0.9 * var(--mainFontSize));
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 5px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.at-settings-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.at-settings-option {
|
||||
flex: 1;
|
||||
margin: 0 10px;
|
||||
}
|
||||
|
||||
.at-endpoint-option {
|
||||
flex: 1;
|
||||
margin: 0 10px;
|
||||
margin-right: 25px;
|
||||
width: 38%;
|
||||
}
|
||||
|
||||
.at-website-row {
|
||||
display: flex;
|
||||
justify-content: start;
|
||||
align-items: center;
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.at-website-option {
|
||||
flex: 1;
|
||||
margin-right: 10px;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.at-settings-separator {
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
padding: 18x;
|
||||
font-weight: bold;
|
||||
border-top: 1px solid #e1e1e1; /* Grey line */
|
||||
border-bottom: 1px solid #e1e1e1; /* Grey line */
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.at-status-message {
|
||||
flex: 1;
|
||||
margin: 0 10px;
|
||||
}
|
||||
|
||||
.at-model-endpoint-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.at-model-option, .endpoint-option {
|
||||
flex: 1;
|
||||
margin: 0 10px;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.at-endpoint-option {
|
||||
width: 38%;
|
||||
}
|
||||
|
||||
#at-status_info {
|
||||
color: lightgreen;
|
||||
}
|
||||
@@ -1,269 +0,0 @@
|
||||
import json
|
||||
import argparse
|
||||
from pathlib import Path
|
||||
import os
|
||||
import glob
|
||||
import platform
|
||||
import site
|
||||
import subprocess
|
||||
import sys
|
||||
# version 0.8
|
||||
|
||||
def find_files_in_path_with_wildcard(pattern):
|
||||
# Get the site-packages directory of the current Python environment
|
||||
site_packages_path = site.getsitepackages()
|
||||
found_paths = []
|
||||
# Adjust the sub-directory based on the operating system
|
||||
sub_directory = "nvidia/cublas"
|
||||
if platform.system() == "Linux":
|
||||
sub_directory = os.path.join(sub_directory, "lib")
|
||||
else:
|
||||
sub_directory = os.path.join(sub_directory, "bin")
|
||||
|
||||
# Iterate over each site-packages directory (there can be more than one)
|
||||
for directory in site_packages_path:
|
||||
# Construct the search directory path
|
||||
search_directory = os.path.join(directory, sub_directory)
|
||||
# Use glob to find all files matching the pattern in this directory
|
||||
for file_path in glob.glob(os.path.join(search_directory, pattern)):
|
||||
if os.path.isfile(file_path): # Ensure it's a file
|
||||
found_paths.append(file_path)
|
||||
return found_paths
|
||||
|
||||
def detect_cublas():
|
||||
# Use different file patterns based on the operating system
|
||||
file_name_pattern = 'cublas64_11.*' if platform.system() == "Windows" else 'libcublas.so.11*'
|
||||
found_paths = find_files_in_path_with_wildcard(file_name_pattern)
|
||||
if found_paths:
|
||||
print("[AllTalk TTSDiff] \033[94mCublas:\033[0m \033[92mDetected\033[0m", found_paths)
|
||||
else:
|
||||
print("[AllTalk TTSDiff] \033[94mCublas:\033[0m \033[91mERROR Not Detected\033[0m")
|
||||
print("[AllTalk TTSDiff] \033[94mPlease install Cublas from the Nvidia CUDA Toolkit \033[0mhttps://developer.nvidia.com/cuda-downloads")
|
||||
exit(1)
|
||||
|
||||
|
||||
parser = argparse.ArgumentParser(description="Compare TTS output with the original text using detailed comparison.")
|
||||
parser.add_argument("--threshold", type=int, default=98, help="Similarity threshold for considering a match (default: 98)")
|
||||
parser.add_argument("--ttslistpath", help="Path to the ttsList.json file")
|
||||
parser.add_argument("--wavfilespath", help="Path to the wav outputs folder")
|
||||
args = parser.parse_args()
|
||||
|
||||
if not args.ttslistpath:
|
||||
parser.error("[AllTalk TTSDiff] Please specify the path to the ttslist.json file using the --ttslistpath argument.")
|
||||
if not args.wavfilespath:
|
||||
parser.error("[AllTalk TTSDiff] Please specify the path to the wavs output folder file using the --wavfilespath argument.")
|
||||
|
||||
json_file_path = Path(args.ttslistpath).resolve()
|
||||
wav_file_path = Path(args.wavfilespath).resolve()
|
||||
accuracy_threshold = args.threshold
|
||||
|
||||
def disclaimer_text():
|
||||
print(f"\nDESCRIPTION: ")
|
||||
print(f" This script is designed to assist in identifying bad TTS generation ID's from the TTS Generator.\n")
|
||||
print(f" This will download the Whisper Large-v2 model (if not already downloaded), and use it to compare your text to")
|
||||
print(f" to the generated TTS. If it finds an issue, it will flag the ID number that has the issue. This does NOT 100%")
|
||||
print(f" ensure that all TTS generated is perfect, sounds good etc, but it should flag up glaring issues and help with")
|
||||
print(f" the process of identifying bad TTS generations.")
|
||||
print(f"\nNOTES ON USE: ")
|
||||
print(f" - Ensure AllTalk is running in its own command prompt/terminal.")
|
||||
print(f" - This script should be running in its own command prompt/terminal window in the same Python Environment that")
|
||||
print(f" AllTalk is running in.")
|
||||
print(f" - After generating your text in the TTS Generator, you need to `Export List to JSON` and save the file in the")
|
||||
print(f" same folder/directory this script is running from.")
|
||||
print(f" - You can use `--threshold` with a numerical value from 1 to 100 to set accuracy detection. For example it may")
|
||||
print(f" detect/transcribe `their` as `there`, which of course, both words sound the same. If you want 100% accuracy")
|
||||
print(f" you will set 100 as the threshold. You will more than likely want a number in the high 90's. Default is set")
|
||||
print(f" at 98, which gives a little flexibility.")
|
||||
print(f" - The JSON file must be named \033[93mttsList.json\033[0m")
|
||||
print(f" - When you have your ID list, go back into the TTS Generator, correct any lines and regenerate them. If you")
|
||||
print(f" want to re-test everthing again after re-generating, you will need to export your list again and re-run this")
|
||||
print(f" script again, against your newly exported JSON list.")
|
||||
print(f" - This requires access to \033[93mcublas64_11\033[0m, the same as Finetuning.")
|
||||
print(f" https://github.com/erew123/alltalk_tts/tree/main?#-important-requirements-cuda-118\n")
|
||||
return
|
||||
|
||||
try:
|
||||
from faster_whisper import WhisperModel
|
||||
import re
|
||||
import string
|
||||
import spacy
|
||||
import torch
|
||||
from fuzzywuzzy import fuzz
|
||||
except ImportError as e:
|
||||
print(f"[AllTalk TTSDiff] ERROR STARTING SCRIPT:")
|
||||
print("[AllTalk TTSDiff] An error occurred importing one or more required libraries.")
|
||||
print("[AllTalk TTSDiff] Please ensure you have \033[94mactivated your Python environment \033[0mand \033[94minstalled all requirements.\033[0m")
|
||||
print("[AllTalk TTSDiff] \033[94mMissing library:\033[93m", str(e), "\033[0m")
|
||||
exit(1)
|
||||
|
||||
# Attempt to load the spaCy model
|
||||
try:
|
||||
# Load a medium-sized spaCy model, adjust to "en_core_web_md" or "en_core_web_lg" as needed
|
||||
nlp = spacy.load("en_core_web_md")
|
||||
except Exception as e:
|
||||
print(f"[AllTalk TTSDiff] ERROR STARTING SCRIPT:")
|
||||
print("[AllTalk TTSDiff] Failed to load the spaCy language model.")
|
||||
|
||||
# Attempt to download the spaCy model automatically
|
||||
try:
|
||||
print("[AllTalk TTSDiff] Attempting to automatically download the spaCy language model...")
|
||||
subprocess.run([sys.executable, "-m", "spacy", "download", "en_core_web_md"], check=True)
|
||||
|
||||
# Try to load the model again after downloading
|
||||
nlp = spacy.load("en_core_web_md")
|
||||
print("[AllTalk TTSDiff] Model downloaded and loaded successfully.")
|
||||
except Exception as download_exception:
|
||||
print("[AllTalk TTSDiff] Automatic download failed.")
|
||||
print("[AllTalk TTSDiff] Please manually install the spaCy language model by running:")
|
||||
print("[AllTalk TTSDiff] \033[93mpython -m spacy download en_core_web_md\033[0m")
|
||||
exit(1)
|
||||
|
||||
def texts_are_similar(text1, text2, threshold=0.8):
|
||||
# Preliminary check for short texts
|
||||
if len(text1) < 10 or len(text2) < 10:
|
||||
ratio = fuzz.ratio(text1, text2) / 100.0 # Use FuzzyWuzzy for short texts
|
||||
return ratio > threshold
|
||||
|
||||
# Process the texts through the NLP model for longer texts
|
||||
doc1 = nlp(text1)
|
||||
doc2 = nlp(text2)
|
||||
|
||||
# Compute semantic similarity
|
||||
similarity = doc1.similarity(doc2)
|
||||
|
||||
return similarity >= threshold
|
||||
|
||||
def normalize_text(text):
|
||||
# Normalize or remove CRLF and other non-standard whitespaces
|
||||
text = text.replace("\r\n", " ").replace("\n", " ").replace("\r", " ")
|
||||
|
||||
# Convert to lowercase
|
||||
text = text.lower()
|
||||
|
||||
# Standardize and then remove quotation marks
|
||||
text = text.replace("“", '"').replace("”", '"').replace("‘", "'").replace("’", "'")
|
||||
text = text.translate(str.maketrans('', '', '"\''))
|
||||
|
||||
# Remove all other punctuation except hyphens to preserve compound words
|
||||
text = text.translate(str.maketrans('', '', string.punctuation.replace("-", "")))
|
||||
|
||||
# Collapse any sequence of whitespace (including spaces) into a single space
|
||||
text = re.sub(r'\s+', ' ', text)
|
||||
|
||||
return text.strip()
|
||||
|
||||
spoken_punctuation_mapping = {
|
||||
"dot": ".",
|
||||
"comma": ",",
|
||||
# Add more mappings as needed
|
||||
}
|
||||
|
||||
def contains_spoken_punctuation(transcribed_text):
|
||||
for spoken, punctuation in spoken_punctuation_mapping.items():
|
||||
if spoken in transcribed_text:
|
||||
return True
|
||||
return False
|
||||
|
||||
def detailed_comparison(original_text, transcribed_text, threshold=98):
|
||||
original_clean = normalize_text(original_text)
|
||||
transcribed_clean = normalize_text(transcribed_text)
|
||||
ratio = fuzz.ratio(original_clean, transcribed_clean)
|
||||
return ratio > threshold
|
||||
|
||||
def access_local_file(url):
|
||||
# Extract the file name from the URL
|
||||
file_name = url.split('/')[-1]
|
||||
# Construct the full path to the file on disk
|
||||
file_path = wav_file_path / file_name
|
||||
# Check if the file exists
|
||||
if not file_path.exists():
|
||||
print(f"[AllTalk TTSDiff] File does not exist: {file_path}")
|
||||
return None
|
||||
return file_path
|
||||
|
||||
def transcribe_and_compare(file_url, original_text, model, item_id, flagged_ids):
|
||||
audio_file_path = access_local_file(file_url)
|
||||
if audio_file_path is None:
|
||||
print(f"[AllTalk TTSDiff] Could not access local file for URL: {file_url}")
|
||||
return # Skip this file if it can't be accessed
|
||||
|
||||
try:
|
||||
segments, info = model.transcribe(str(audio_file_path), beam_size=5)
|
||||
transcribed_text = " ".join([segment.text for segment in segments])
|
||||
except Exception as e:
|
||||
print(f"[AllTalk TTSDiff] Error transcribing file {audio_file_path}: {e}")
|
||||
return # Skip this file if transcription fails
|
||||
|
||||
segments, info = model.transcribe(str(audio_file_path), beam_size=5)
|
||||
transcribed_text = " ".join([segment.text for segment in segments])
|
||||
|
||||
# Normalize texts for comparison
|
||||
original_text_normalized = normalize_text(original_text)
|
||||
transcribed_text_normalized = normalize_text(transcribed_text)
|
||||
|
||||
# Enhanced comparison using detailed fuzzy matching
|
||||
is_detailed_match = detailed_comparison(original_text_normalized, transcribed_text_normalized, args.threshold)
|
||||
has_spoken_punctuation = contains_spoken_punctuation(transcribed_text_normalized) and not contains_spoken_punctuation(original_text_normalized)
|
||||
|
||||
# Adjust is_match based on detailed comparison and spoken punctuation check
|
||||
is_match = is_detailed_match and not has_spoken_punctuation
|
||||
|
||||
# Only log and flag IDs for review if there's a mismatch or detected issues
|
||||
if not is_match:
|
||||
#print(f"\033[93mMismatch Detected - ID:\033[0m {item_id}")
|
||||
print(f"[AllTalk TTSDiff] \033[93mText:\033[0m {original_text}")
|
||||
print(f"[AllTalk TTSDiff] \033[91mTTS :\033[0m{transcribed_text}")
|
||||
if has_spoken_punctuation:
|
||||
print(f"[AllTalk TTSDiff] Note: Potential incorrect spoken punctuation detected.")
|
||||
flagged_ids.append(item_id) # Track the ID for review
|
||||
|
||||
def main():
|
||||
print(f"[AllTalk TTSDiff]")
|
||||
print(f"[AllTalk TTSDiff]")
|
||||
print("[AllTalk TTSDiff] \033[92mStarting Compare of Text vs TTS:\033[0m")
|
||||
print("[AllTalk TTSDiff]")
|
||||
print("[AllTalk TTSDiff] \033[94mJSON file :\033[92m", json_file_path, "\033[0m")
|
||||
print("[AllTalk TTSDiff] \033[94mWAV files :\033[92m", wav_file_path, "\033[0m")
|
||||
print("[AllTalk TTSDiff] \033[94mAccuracy :\033[92m", accuracy_threshold, "%", "\033[0m")
|
||||
detect_cublas()
|
||||
model_size = "large-v2"
|
||||
device = "cuda" if torch.cuda.is_available() else "cpu"
|
||||
model = WhisperModel(model_size, device=device, compute_type="float32")
|
||||
|
||||
flagged_ids = [] # Initialize the list to track IDs needing review
|
||||
|
||||
try:
|
||||
with open(json_file_path, "r", encoding="utf-8") as f:
|
||||
tts_list = json.load(f)
|
||||
except FileNotFoundError:
|
||||
print(f"[AllTalk TTSDiff] ERROR STARTING SCRIPT:")
|
||||
print("[AllTalk TTSDiff] Error: \033[93mttsList.json\033[0m file not found.")
|
||||
print("[AllTalk TTSDiff] Please ensure you follow these steps:")
|
||||
print("[AllTalk TTSDiff] After generating your text in the TTS Generator, you need to `Export List to JSON` and save the file in the")
|
||||
print("[AllTalk TTSDiff] same folder/directory this script is running from.")
|
||||
print("[AllTalk TTSDiff] The JSON file must be named \033[93mttsList.json\033[0m")
|
||||
exit(1)
|
||||
|
||||
print(f"[AllTalk TTSDiff]")
|
||||
|
||||
for item in tts_list:
|
||||
print(f"[AllTalk TTSDiff] Processing ID: {item['id']}")
|
||||
transcribe_and_compare(item['fileUrl'], item['text'], model, item['id'], flagged_ids)
|
||||
|
||||
print(f"[AllTalk TTSDiff]")
|
||||
# Print summary information at the end
|
||||
if flagged_ids:
|
||||
print(f"[AllTalk TTSDiff] \033[94mIDs needing review:\033[0m", ', '.join(map(str, flagged_ids)))
|
||||
print(f"[AllTalk TTSDiff]")
|
||||
print(f"[AllTalk TTSDiff] Review ID's and correct any lines by editing & regenerating as necessary.")
|
||||
else:
|
||||
print("[AllTalk TTSDiff] \033[94mIDs needing review:\033[0m No issues detected.")
|
||||
summary_data = {
|
||||
"flagged_ids": flagged_ids
|
||||
}
|
||||
with open(wav_file_path / "analysis_summary.json", "w") as summary_file:
|
||||
json.dump(summary_data, summary_file)
|
||||
print("[AllTalk TTSDiff]")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -1,179 +0,0 @@
|
||||
export interface CrunkerConstructorOptions {
|
||||
/**
|
||||
* Sample rate for Crunker's internal audio context.
|
||||
*
|
||||
* @default 44100
|
||||
*/
|
||||
sampleRate: number;
|
||||
}
|
||||
export type CrunkerInputTypes = string | File | Blob;
|
||||
/**
|
||||
* An exported Crunker audio object.
|
||||
*/
|
||||
export interface ExportedCrunkerAudio {
|
||||
blob: Blob;
|
||||
url: string;
|
||||
element: HTMLAudioElement;
|
||||
}
|
||||
/**
|
||||
* Crunker is the simple way to merge, concatenate, play, export and download audio files using the Web Audio API.
|
||||
*/
|
||||
export default class Crunker {
|
||||
private readonly _sampleRate;
|
||||
private readonly _context;
|
||||
/**
|
||||
* Creates a new instance of Crunker with the provided options.
|
||||
*
|
||||
* If `sampleRate` is not defined, it will auto-select an appropriate sample rate
|
||||
* for the device being used.
|
||||
*/
|
||||
constructor({ sampleRate }?: Partial<CrunkerConstructorOptions>);
|
||||
/**
|
||||
* Creates Crunker's internal AudioContext.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
private _createContext;
|
||||
/**
|
||||
*
|
||||
* The internal AudioContext used by Crunker.
|
||||
*/
|
||||
get context(): AudioContext;
|
||||
/**
|
||||
* Asynchronously fetches multiple audio files and returns an array of AudioBuffers.
|
||||
*/
|
||||
fetchAudio(...filepaths: CrunkerInputTypes[]): Promise<AudioBuffer[]>;
|
||||
/**
|
||||
* Merges (layers) multiple AudioBuffers into a single AudioBuffer.
|
||||
*
|
||||
* **Visual representation:**
|
||||
*
|
||||
* 
|
||||
*/
|
||||
mergeAudio(buffers: AudioBuffer[]): AudioBuffer;
|
||||
/**
|
||||
* Concatenates multiple AudioBuffers into a single AudioBuffer.
|
||||
*
|
||||
* **Visual representation:**
|
||||
*
|
||||
* 
|
||||
*/
|
||||
concatAudio(buffers: AudioBuffer[]): AudioBuffer;
|
||||
/**
|
||||
* Pads a specified AudioBuffer with silence from a specified start time,
|
||||
* for a specified length of time.
|
||||
*
|
||||
* Accepts float values as well as whole integers.
|
||||
*
|
||||
* @param buffer AudioBuffer to pad
|
||||
* @param padStart Time to start padding (in seconds)
|
||||
* @param seconds Duration to pad for (in seconds)
|
||||
*/
|
||||
padAudio(buffer: AudioBuffer, padStart?: number, seconds?: number): AudioBuffer;
|
||||
/**
|
||||
* Slices an AudioBuffer from the specified start time to the end time, with optional fade in and out.
|
||||
*
|
||||
* @param buffer AudioBuffer to slice
|
||||
* @param start Start time (in seconds)
|
||||
* @param end End time (in seconds)
|
||||
* @param fadeIn Fade in duration (in seconds, default is 0)
|
||||
* @param fadeOut Fade out duration (in seconds, default is 0)
|
||||
*/
|
||||
sliceAudio(buffer: AudioBuffer, start: number, end: number, fadeIn?: number, fadeOut?: number): AudioBuffer;
|
||||
/**
|
||||
* Plays the provided AudioBuffer in an AudioBufferSourceNode.
|
||||
*/
|
||||
play(buffer: AudioBuffer): AudioBufferSourceNode;
|
||||
/**
|
||||
* Exports the specified AudioBuffer to a Blob, Object URI and HTMLAudioElement.
|
||||
*
|
||||
* Note that changing the MIME type does not change the actual file format. The
|
||||
* file format will **always** be a WAVE file due to how audio is stored in the
|
||||
* browser.
|
||||
*
|
||||
* @param buffer Buffer to export
|
||||
* @param type MIME type (default: `audio/wav`)
|
||||
*/
|
||||
export(buffer: AudioBuffer, type?: string): ExportedCrunkerAudio;
|
||||
/**
|
||||
* Downloads the provided Blob.
|
||||
*
|
||||
* @param blob Blob to download
|
||||
* @param filename An optional file name to use for the download (default: `crunker`)
|
||||
*/
|
||||
download(blob: Blob, filename?: string): HTMLAnchorElement;
|
||||
/**
|
||||
* Executes a callback if the browser does not support the Web Audio API.
|
||||
*
|
||||
* Returns the result of the callback, or `undefined` if the Web Audio API is supported.
|
||||
*
|
||||
* @param callback callback to run if the browser does not support the Web Audio API
|
||||
*/
|
||||
notSupported<T>(callback: () => T): T | undefined;
|
||||
/**
|
||||
* Closes Crunker's internal AudioContext.
|
||||
*/
|
||||
close(): this;
|
||||
/**
|
||||
* Returns the largest duration of the longest AudioBuffer.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
private _maxDuration;
|
||||
/**
|
||||
* Returns the largest number of channels in an array of AudioBuffers.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
private _maxNumberOfChannels;
|
||||
/**
|
||||
* Returns the sum of the lengths of an array of AudioBuffers.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
private _totalLength;
|
||||
/**
|
||||
* Returns whether the browser supports the Web Audio API.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
private _isSupported;
|
||||
/**
|
||||
* Writes the WAV headers for the specified Float32Array.
|
||||
*
|
||||
* Returns a DataView containing the WAV headers and file content.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
private _writeHeaders;
|
||||
/**
|
||||
* Converts a Float32Array to 16-bit PCM.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
private _floatTo16BitPCM;
|
||||
/**
|
||||
* Writes a string to a DataView at the specified offset.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
private _writeString;
|
||||
/**
|
||||
* Converts an AudioBuffer to a Float32Array.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
private _interleave;
|
||||
/**
|
||||
* Creates an HTMLAudioElement whose source is the specified Blob.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
private _renderAudioElement;
|
||||
/**
|
||||
* Creates an Object URL for the specified Blob.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
private _renderURL;
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
var e={d:(t,n)=>{for(var r in n)e.o(n,r)&&!e.o(t,r)&&Object.defineProperty(t,r,{enumerable:!0,get:n[r]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t)},t={};function n(e){return n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},n(e)}function r(e){return function(e){if(Array.isArray(e))return a(e)}(e)||function(e){if("undefined"!=typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}(e)||function(e,t){if(!e)return;if("string"==typeof e)return a(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);"Object"===n&&e.constructor&&(n=e.constructor.name);if("Map"===n||"Set"===n)return Array.from(e);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return a(e,t)}(e)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function a(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n<t;n++)r[n]=e[n];return r}function o(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function i(e,t){for(var r=0;r<t.length;r++){var a=t[r];a.enumerable=a.enumerable||!1,a.configurable=!0,"value"in a&&(a.writable=!0),Object.defineProperty(e,(o=a.key,i=void 0,i=function(e,t){if("object"!==n(e)||null===e)return e;var r=e[Symbol.toPrimitive];if(void 0!==r){var a=r.call(e,t||"default");if("object"!==n(a))return a;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(o,"string"),"symbol"===n(i)?i:String(i)),a)}var o,i}e.d(t,{Z:()=>u});var u=function(){function e(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=t.sampleRate;o(this,e),this._context=this._createContext(n),n||(n=this._context.sampleRate),this._sampleRate=n}var t,n,a;return t=e,n=[{key:"_createContext",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:44100;return window.AudioContext=window.AudioContext||window.webkitAudioContext||window.mozAudioContext,new AudioContext({sampleRate:e})}},{key:"context",get:function(){return this._context}},{key:"fetchAudio",value:async function(){for(var e=this,t=arguments.length,n=new Array(t),r=0;r<t;r++)n[r]=arguments[r];return await Promise.all(n.map((async function(t){var n;return n=t instanceof File||t instanceof Blob?await t.arrayBuffer():await fetch(t).then((function(e){return e.headers.has("Content-Type")&&!e.headers.get("Content-Type").includes("audio/")&&console.warn("Crunker: Attempted to fetch an audio file, but its MIME type is `".concat(e.headers.get("Content-Type").split(";")[0],"`. We'll try and continue anyway. (file: \"").concat(t,'")')),e.arrayBuffer()})),await e._context.decodeAudioData(n)})))}},{key:"mergeAudio",value:function(e){var t=this._context.createBuffer(this._maxNumberOfChannels(e),this._sampleRate*this._maxDuration(e),this._sampleRate);return e.forEach((function(e){for(var n=0;n<e.numberOfChannels;n++){for(var r=t.getChannelData(n),a=e.getChannelData(n),o=e.getChannelData(n).length-1;o>=0;o--)r[o]+=a[o];t.getChannelData(n).set(r)}})),t}},{key:"concatAudio",value:function(e){var t=this._context.createBuffer(this._maxNumberOfChannels(e),this._totalLength(e),this._sampleRate),n=0;return e.forEach((function(e){for(var r=0;r<e.numberOfChannels;r++)t.getChannelData(r).set(e.getChannelData(r),n);n+=e.length})),t}},{key:"padAudio",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0;if(0===n)return e;if(t<0)throw new Error('Crunker: Parameter "padStart" in padAudio must be positive');if(n<0)throw new Error('Crunker: Parameter "seconds" in padAudio must be positive');for(var r=this._context.createBuffer(e.numberOfChannels,Math.ceil(e.length+n*e.sampleRate),e.sampleRate),a=0;a<e.numberOfChannels;a++){var o=e.getChannelData(a);r.getChannelData(a).set(o.subarray(0,Math.ceil(t*e.sampleRate)+1),0),r.getChannelData(a).set(o.subarray(Math.ceil(t*e.sampleRate)+2,r.length+1),Math.ceil((t+n)*e.sampleRate))}return r}},{key:"sliceAudio",value:function(e,t,n){var r=arguments.length>3&&void 0!==arguments[3]?arguments[3]:0,a=arguments.length>4&&void 0!==arguments[4]?arguments[4]:0;if(t>=n)throw new Error('Crunker: "start" time should be less than "end" time in sliceAudio method');for(var o=Math.round((n-t)*this._sampleRate),i=Math.round(t*this._sampleRate),u=this._context.createBuffer(e.numberOfChannels,o,this._sampleRate),l=0;l<e.numberOfChannels;l++)for(var s=e.getChannelData(l),c=u.getChannelData(l),f=0;f<o;f++)c[f]=s[i+f],f<r*this._sampleRate&&(c[f]*=f/(r*this._sampleRate)),f>o-a*this._sampleRate&&(c[f]*=(o-f)/(a*this._sampleRate));return u}},{key:"play",value:function(e){var t=this._context.createBufferSource();return t.buffer=e,t.connect(this._context.destination),t.start(),Line truncated
|
||||
//# sourceMappingURL=crunker.esm.js.map
|
||||
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"crunker.esm.js","mappings":"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 truncated
|
||||
|
Before Width: | Height: | Size: 1.1 KiB |
@@ -1,4 +0,0 @@
|
||||
/*! howler.js v2.2.4 | (c) 2013-2020, James Simpson of GoldFire Studios | MIT License | howlerjs.com */
|
||||
!function(){"use strict";var e=function(){this.init()};e.prototype={init:function(){var e=this||n;return e._counter=1e3,e._html5AudioPool=[],e.html5PoolSize=10,e._codecs={},e._howls=[],e._muted=!1,e._volume=1,e._canPlayEvent="canplaythrough",e._navigator="undefined"!=typeof window&&window.navigator?window.navigator:null,e.masterGain=null,e.noAudio=!1,e.usingWebAudio=!0,e.autoSuspend=!0,e.ctx=null,e.autoUnlock=!0,e._setup(),e},volume:function(e){var o=this||n;if(e=parseFloat(e),o.ctx||_(),void 0!==e&&e>=0&&e<=1){if(o._volume=e,o._muted)return o;o.usingWebAudio&&o.masterGain.gain.setValueAtTime(e,n.ctx.currentTime);for(var t=0;t<o._howls.length;t++)if(!o._howls[t]._webAudio)for(var r=o._howls[t]._getSoundIds(),a=0;a<r.length;a++){var u=o._howls[t]._soundById(r[a]);u&&u._node&&(u._node.volume=u._volume*e)}return o}return o._volume},mute:function(e){var o=this||n;o.ctx||_(),o._muted=e,o.usingWebAudio&&o.masterGain.gain.setValueAtTime(e?0:o._volume,n.ctx.currentTime);for(var t=0;t<o._howls.length;t++)if(!o._howls[t]._webAudio)for(var r=o._howls[t]._getSoundIds(),a=0;a<r.length;a++){var u=o._howls[t]._soundById(r[a]);u&&u._node&&(u._node.muted=!!e||u._muted)}return o},stop:function(){for(var e=this||n,o=0;o<e._howls.length;o++)e._howls[o].stop();return e},unload:function(){for(var e=this||n,o=e._howls.length-1;o>=0;o--)e._howls[o].unload();return e.usingWebAudio&&e.ctx&&void 0!==e.ctx.close&&(e.ctx.close(),e.ctx=null,_()),e},codecs:function(e){return(this||n)._codecs[e.replace(/^x-/,"")]},_setup:function(){var e=this||n;if(e.state=e.ctx?e.ctx.state||"suspended":"suspended",e._autoSuspend(),!e.usingWebAudio)if("undefined"!=typeof Audio)try{var o=new Audio;void 0===o.oncanplaythrough&&(e._canPlayEvent="canplay")}catch(n){e.noAudio=!0}else e.noAudio=!0;try{var o=new Audio;o.muted&&(e.noAudio=!0)}catch(e){}return e.noAudio||e._setupCodecs(),e},_setupCodecs:function(){var e=this||n,o=null;try{o="undefined"!=typeof Audio?new Audio:null}catch(n){return e}if(!o||"function"!=typeof o.canPlayType)return e;var t=o.canPlayType("audio/mpeg;").replace(/^no$/,""),r=e._navigator?e._navigator.userAgent:"",a=r.match(/OPR\/(\d+)/g),u=a&&parseInt(a[0].split("/")[1],10)<33,d=-1!==r.indexOf("Safari")&&-1===r.indexOf("Chrome"),i=r.match(/Version\/(.*?) /),_=d&&i&&parseInt(i[1],10)<15;return e._codecs={mp3:!(u||!t&&!o.canPlayType("audio/mp3;").replace(/^no$/,"")),mpeg:!!t,opus:!!o.canPlayType('audio/ogg; codecs="opus"').replace(/^no$/,""),ogg:!!o.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/,""),oga:!!o.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/,""),wav:!!(o.canPlayType('audio/wav; codecs="1"')||o.canPlayType("audio/wav")).replace(/^no$/,""),aac:!!o.canPlayType("audio/aac;").replace(/^no$/,""),caf:!!o.canPlayType("audio/x-caf;").replace(/^no$/,""),m4a:!!(o.canPlayType("audio/x-m4a;")||o.canPlayType("audio/m4a;")||o.canPlayType("audio/aac;")).replace(/^no$/,""),m4b:!!(o.canPlayType("audio/x-m4b;")||o.canPlayType("audio/m4b;")||o.canPlayType("audio/aac;")).replace(/^no$/,""),mp4:!!(o.canPlayType("audio/x-mp4;")||o.canPlayType("audio/mp4;")||o.canPlayType("audio/aac;")).replace(/^no$/,""),weba:!(_||!o.canPlayType('audio/webm; codecs="vorbis"').replace(/^no$/,"")),webm:!(_||!o.canPlayType('audio/webm; codecs="vorbis"').replace(/^no$/,"")),dolby:!!o.canPlayType('audio/mp4; codecs="ec-3"').replace(/^no$/,""),flac:!!(o.canPlayType("audio/x-flac;")||o.canPlayType("audio/flac;")).replace(/^no$/,"")},e},_unlockAudio:function(){var e=this||n;if(!e._audioUnlocked&&e.ctx){e._audioUnlocked=!1,e.autoUnlock=!1,e._mobileUnloaded||44100===e.ctx.sampleRate||(e._mobileUnloaded=!0,e.unload()),e._scratchBuffer=e.ctx.createBuffer(1,1,22050);var o=function(n){for(;e._html5AudioPool.length<e.html5PoolSize;)try{var t=new Audio;t._unlocked=!0,e._releaseHtml5Audio(t)}catch(n){e.noAudio=!0;break}for(var r=0;r<e._howls.length;r++)if(!e._howls[r]._webAudio)for(var a=e._howls[r]._getSoundIds(),u=0;u<a.length;u++){var d=e._howls[r]._soundById(a[u]);d&&d._node&&!d._node._unlocked&&(d._node._unlocked=!0,d._node.load())}e._autoResume();var i=e.ctx.createBufferSource();i.buffer=e._scratchBuffer,i.connect(e.ctx.destination),void 0===i.start?i.noteOn(0):i.start(0),"function"==typeof e.ctx.resume&&e.ctx.resume(),i.onended=function(){i.disconnect(0),e._audioUnlocked=!0,document.removeEventListener("touchstart",o,!0),document.removeEventListener("touchend",o,!0),document.removeEventListener("click",o,!0),document.removeEventListener("keydown",o,!0);for(var n=0;n<e._howls.length;n++)e._howls[n]._emit("unlock")}};return document.addEventListener("touchstart",o,!0),document.addEventListener("touchend",o,!0),document.addEventListener("click",o,!0),document.addEventListener("keydown",o,!0),e}},_obtainHtml5Audio:function(){var e=this||n;if(e._html5AudioPool.length)return e._html5AudioPool.pop();var o=(new Audio).play();return o&&"undefined"!=typeof Promise&&(o instanceof Promise||"function"==typeof o.then)&&o.catch(function(){console.warn("HTML5 Audio pool eLine truncated
|
||||
/*! Spatial Plugin */
|
||||
!function(){"use strict";HowlerGlobal.prototype._pos=[0,0,0],HowlerGlobal.prototype._orientation=[0,0,-1,0,1,0],HowlerGlobal.prototype.stereo=function(e){var n=this;if(!n.ctx||!n.ctx.listener)return n;for(var t=n._howls.length-1;t>=0;t--)n._howls[t].stereo(e);return n},HowlerGlobal.prototype.pos=function(e,n,t){var r=this;return r.ctx&&r.ctx.listener?(n="number"!=typeof n?r._pos[1]:n,t="number"!=typeof t?r._pos[2]:t,"number"!=typeof e?r._pos:(r._pos=[e,n,t],void 0!==r.ctx.listener.positionX?(r.ctx.listener.positionX.setTargetAtTime(r._pos[0],Howler.ctx.currentTime,.1),r.ctx.listener.positionY.setTargetAtTime(r._pos[1],Howler.ctx.currentTime,.1),r.ctx.listener.positionZ.setTargetAtTime(r._pos[2],Howler.ctx.currentTime,.1)):r.ctx.listener.setPosition(r._pos[0],r._pos[1],r._pos[2]),r)):r},HowlerGlobal.prototype.orientation=function(e,n,t,r,o,i){var a=this;if(!a.ctx||!a.ctx.listener)return a;var p=a._orientation;return n="number"!=typeof n?p[1]:n,t="number"!=typeof t?p[2]:t,r="number"!=typeof r?p[3]:r,o="number"!=typeof o?p[4]:o,i="number"!=typeof i?p[5]:i,"number"!=typeof e?p:(a._orientation=[e,n,t,r,o,i],void 0!==a.ctx.listener.forwardX?(a.ctx.listener.forwardX.setTargetAtTime(e,Howler.ctx.currentTime,.1),a.ctx.listener.forwardY.setTargetAtTime(n,Howler.ctx.currentTime,.1),a.ctx.listener.forwardZ.setTargetAtTime(t,Howler.ctx.currentTime,.1),a.ctx.listener.upX.setTargetAtTime(r,Howler.ctx.currentTime,.1),a.ctx.listener.upY.setTargetAtTime(o,Howler.ctx.currentTime,.1),a.ctx.listener.upZ.setTargetAtTime(i,Howler.ctx.currentTime,.1)):a.ctx.listener.setOrientation(e,n,t,r,o,i),a)},Howl.prototype.init=function(e){return function(n){var t=this;return t._orientation=n.orientation||[1,0,0],t._stereo=n.stereo||null,t._pos=n.pos||null,t._pannerAttr={coneInnerAngle:void 0!==n.coneInnerAngle?n.coneInnerAngle:360,coneOuterAngle:void 0!==n.coneOuterAngle?n.coneOuterAngle:360,coneOuterGain:void 0!==n.coneOuterGain?n.coneOuterGain:0,distanceModel:void 0!==n.distanceModel?n.distanceModel:"inverse",maxDistance:void 0!==n.maxDistance?n.maxDistance:1e4,panningModel:void 0!==n.panningModel?n.panningModel:"HRTF",refDistance:void 0!==n.refDistance?n.refDistance:1,rolloffFactor:void 0!==n.rolloffFactor?n.rolloffFactor:1},t._onstereo=n.onstereo?[{fn:n.onstereo}]:[],t._onpos=n.onpos?[{fn:n.onpos}]:[],t._onorientation=n.onorientation?[{fn:n.onorientation}]:[],e.call(this,n)}}(Howl.prototype.init),Howl.prototype.stereo=function(n,t){var r=this;if(!r._webAudio)return r;if("loaded"!==r._state)return r._queue.push({event:"stereo",action:function(){r.stereo(n,t)}}),r;var o=void 0===Howler.ctx.createStereoPanner?"spatial":"stereo";if(void 0===t){if("number"!=typeof n)return r._stereo;r._stereo=n,r._pos=[n,0,0]}for(var i=r._getSoundIds(t),a=0;a<i.length;a++){var p=r._soundById(i[a]);if(p){if("number"!=typeof n)return p._stereo;p._stereo=n,p._pos=[n,0,0],p._node&&(p._pannerAttr.panningModel="equalpower",p._panner&&p._panner.pan||e(p,o),"spatial"===o?void 0!==p._panner.positionX?(p._panner.positionX.setValueAtTime(n,Howler.ctx.currentTime),p._panner.positionY.setValueAtTime(0,Howler.ctx.currentTime),p._panner.positionZ.setValueAtTime(0,Howler.ctx.currentTime)):p._panner.setPosition(n,0,0):p._panner.pan.setValueAtTime(n,Howler.ctx.currentTime)),r._emit("stereo",p._id)}}return r},Howl.prototype.pos=function(n,t,r,o){var i=this;if(!i._webAudio)return i;if("loaded"!==i._state)return i._queue.push({event:"pos",action:function(){i.pos(n,t,r,o)}}),i;if(t="number"!=typeof t?0:t,r="number"!=typeof r?-.5:r,void 0===o){if("number"!=typeof n)return i._pos;i._pos=[n,t,r]}for(var a=i._getSoundIds(o),p=0;p<a.length;p++){var s=i._soundById(a[p]);if(s){if("number"!=typeof n)return s._pos;s._pos=[n,t,r],s._node&&(s._panner&&!s._panner.pan||e(s,"spatial"),void 0!==s._panner.positionX?(s._panner.positionX.setValueAtTime(n,Howler.ctx.currentTime),s._panner.positionY.setValueAtTime(t,Howler.ctx.currentTime),s._panner.positionZ.setValueAtTime(r,Howler.ctx.currentTime)):s._panner.setPosition(n,t,r)),i._emit("pos",s._id)}}return i},Howl.prototype.orientation=function(n,t,r,o){var i=this;if(!i._webAudio)return i;if("loaded"!==i._state)return i._queue.push({event:"orientation",action:function(){i.orientation(n,t,r,o)}}),i;if(t="number"!=typeof t?i._orientation[1]:t,r="number"!=typeof r?i._orientation[2]:r,void 0===o){if("number"!=typeof n)return i._orientation;i._orientation=[n,t,r]}for(var a=i._getSoundIds(o),p=0;p<a.length;p++){var s=i._soundById(a[p]);if(s){if("number"!=typeof n)return s._orientation;s._orientation=[n,t,r],s._node&&(s._panner||(s._pos||(s._pos=i._pos||[0,0,-.5]),e(s,"spatial")),void 0!==s._panner.orientationX?(s._panner.orientationX.setValueAtTime(n,Howler.ctx.currentTime),s._panner.orientationY.setValueAtTime(t,Howler.ctx.currentTime),s._panner.orientationZ.setValueAtTime(r,Howler.ctx.currentTime)):s._panner.setOrientation(n,t,r)),i._emit("orientation",s._id)}}return i},Howl.prototype.pannerAttr=function(){var n,t,r,o=this,i=arguments;if(!o._webAudioLine truncated
|
||||
@@ -1,77 +0,0 @@
|
||||
import json
|
||||
import argparse
|
||||
import soundfile as sf
|
||||
from pathlib import Path
|
||||
|
||||
parser = argparse.ArgumentParser(description="Compare TTS output with the original text using detailed comparison.")
|
||||
parser.add_argument("--ttslistpath", help="Path to the ttsList.json file")
|
||||
parser.add_argument("--wavfilespath", help="Path to the wav outputs folder")
|
||||
args = parser.parse_args()
|
||||
|
||||
if not args.ttslistpath:
|
||||
parser.error("[AllTalk TTSSRT] Please specify the path to the ttslist.json file using the --ttslistpath argument.")
|
||||
if not args.wavfilespath:
|
||||
parser.error("[AllTalk TTSSRT] Please specify the path to the wavs output folder file using the --wavfilespath argument.")
|
||||
|
||||
json_file_path = Path(args.ttslistpath).resolve()
|
||||
audio_files_base_path = Path(args.wavfilespath).resolve()
|
||||
|
||||
print(f"[AllTalk TTSSRT]")
|
||||
print("[AllTalk TTSSRT] \033[92mStarting SRT Subtitle generation:\033[0m")
|
||||
print("[AllTalk TTSSRT]")
|
||||
print("[AllTalk TTSSRT] \033[94mJSON file :\033[92m", json_file_path, "\033[0m")
|
||||
print("[AllTalk TTSSRT] \033[94mWAV files :\033[92m", audio_files_base_path, "\033[0m")
|
||||
print("[AllTalk TTSSRT]")
|
||||
|
||||
# Function to convert time in seconds to SRT time format
|
||||
def format_srt_time(seconds):
|
||||
hours = int(seconds // 3600)
|
||||
minutes = int((seconds % 3600) // 60)
|
||||
seconds = seconds % 60
|
||||
milliseconds = int((seconds - int(seconds)) * 1000)
|
||||
return f"{hours:02}:{minutes:02}:{int(seconds):02},{milliseconds:03}"
|
||||
|
||||
# Load the JSON data
|
||||
with open(json_file_path, 'r') as json_file:
|
||||
data = json.load(json_file)
|
||||
|
||||
# Initialize start time and SRT lines
|
||||
start_time = 0.0
|
||||
srt_lines = []
|
||||
|
||||
# Loop through the JSON data to build SRT entries
|
||||
for entry in data:
|
||||
file_name = Path(entry['fileUrl']).name # Get the file name from the URL
|
||||
file_path = audio_files_base_path / file_name
|
||||
print(f"[AllTalk TTSSRT] Processing file: {file_name}")
|
||||
|
||||
if not file_path.exists():
|
||||
print(f"[AllTalk TTSSRT] Audio file does not exist: {file_path}")
|
||||
continue
|
||||
|
||||
try:
|
||||
# Use soundfile to read the duration of the WAV file
|
||||
with sf.SoundFile(str(file_path), 'r') as f:
|
||||
duration = len(f) / f.samplerate
|
||||
end_time = start_time + duration
|
||||
|
||||
# Format the SRT entry
|
||||
start_timestamp = format_srt_time(start_time)
|
||||
end_timestamp = format_srt_time(end_time)
|
||||
srt_lines.append(f"{len(srt_lines)+1}\n{start_timestamp} --> {end_timestamp}\n{entry['text']}\n")
|
||||
|
||||
# Update the start time for the next entry
|
||||
start_time = end_time
|
||||
except RuntimeError as e:
|
||||
print(f"[AllTalk TTSSRT] Error reading {file_path}: {e}")
|
||||
|
||||
# Join all SRT lines into the final SRT content
|
||||
srt_content = "\n".join(srt_lines)
|
||||
|
||||
# Save the SRT content to a file
|
||||
srt_file_path = audio_files_base_path / "subtitles.srt"
|
||||
with open(srt_file_path, "w") as srt_file:
|
||||
srt_file.write(srt_content)
|
||||
|
||||
print("[AllTalk TTSSRT]")
|
||||
print(f"[AllTalk TTSSRT] \033[94mSRT file created at \033[0m{srt_file_path}")
|
||||
@@ -1,2 +0,0 @@
|
||||
/*! For license information please see 1995fcd6d39cade7d871.js.LICENSE.txt */
|
||||
function _typeof(t){return _typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},_typeof(t)}function _regeneratorRuntime(){"use strict";_regeneratorRuntime=function(){return e};var t,e={},r=Object.prototype,n=r.hasOwnProperty,o=Object.defineProperty||function(t,e,r){t[e]=r.value},i="function"==typeof Symbol?Symbol:{},a=i.iterator||"@@iterator",c=i.asyncIterator||"@@asyncIterator",u=i.toStringTag||"@@toStringTag";function l(t,e,r){return Object.defineProperty(t,e,{value:r,enumerable:!0,configurable:!0,writable:!0}),t[e]}try{l({},"")}catch(t){l=function(t,e,r){return t[e]=r}}function f(t,e,r,n){var i=e&&e.prototype instanceof m?e:m,a=Object.create(i.prototype),c=new G(n||[]);return o(a,"_invoke",{value:S(t,r,c)}),a}function s(t,e,r){try{return{type:"normal",arg:t.call(e,r)}}catch(t){return{type:"throw",arg:t}}}e.wrap=f;var h="suspendedStart",p="suspendedYield",y="executing",d="completed",v={};function m(){}function g(){}function w(){}var x={};l(x,a,(function(){return this}));var E=Object.getPrototypeOf,b=E&&E(E(B([])));b&&b!==r&&n.call(b,a)&&(x=b);var T=w.prototype=m.prototype=Object.create(x);function _(t){["next","throw","return"].forEach((function(e){l(t,e,(function(t){return this._invoke(e,t)}))}))}function L(t,e){function r(o,i,a,c){var u=s(t[o],t,i);if("throw"!==u.type){var l=u.arg,f=l.value;return f&&"object"==_typeof(f)&&n.call(f,"__await")?e.resolve(f.__await).then((function(t){r("next",t,a,c)}),(function(t){r("throw",t,a,c)})):e.resolve(f).then((function(t){l.value=t,a(l)}),(function(t){return r("throw",t,a,c)}))}c(u.arg)}var i;o(this,"_invoke",{value:function(t,n){function o(){return new e((function(e,o){r(t,n,e,o)}))}return i=i?i.then(o,o):o()}})}function S(e,r,n){var o=h;return function(i,a){if(o===y)throw new Error("Generator is already running");if(o===d){if("throw"===i)throw a;return{value:t,done:!0}}for(n.method=i,n.arg=a;;){var c=n.delegate;if(c){var u=I(c,n);if(u){if(u===v)continue;return u}}if("next"===n.method)n.sent=n._sent=n.arg;else if("throw"===n.method){if(o===h)throw o=d,n.arg;n.dispatchException(n.arg)}else"return"===n.method&&n.abrupt("return",n.arg);o=y;var l=s(e,r,n);if("normal"===l.type){if(o=n.done?d:p,l.arg===v)continue;return{value:l.arg,done:n.done}}"throw"===l.type&&(o=d,n.method="throw",n.arg=l.arg)}}}function I(e,r){var n=r.method,o=e.iterator[n];if(o===t)return r.delegate=null,"throw"===n&&e.iterator.return&&(r.method="return",r.arg=t,I(e,r),"throw"===r.method)||"return"!==n&&(r.method="throw",r.arg=new TypeError("The iterator does not provide a '"+n+"' method")),v;var i=s(o,e.iterator,r.arg);if("throw"===i.type)return r.method="throw",r.arg=i.arg,r.delegate=null,v;var a=i.arg;return a?a.done?(r[e.resultName]=a.value,r.next=e.nextLoc,"return"!==r.method&&(r.method="next",r.arg=t),r.delegate=null,v):a:(r.method="throw",r.arg=new TypeError("iterator result is not an object"),r.delegate=null,v)}function O(t){var e={tryLoc:t[0]};1 in t&&(e.catchLoc=t[1]),2 in t&&(e.finallyLoc=t[2],e.afterLoc=t[3]),this.tryEntries.push(e)}function j(t){var e=t.completion||{};e.type="normal",delete e.arg,t.completion=e}function G(t){this.tryEntries=[{tryLoc:"root"}],t.forEach(O,this),this.reset(!0)}function B(e){if(e||""===e){var r=e[a];if(r)return r.call(e);if("function"==typeof e.next)return e;if(!isNaN(e.length)){var o=-1,i=function r(){for(;++o<e.length;)if(n.call(e,o))return r.value=e[o],r.done=!1,r;return r.value=t,r.done=!0,r};return i.next=i}}throw new TypeError(_typeof(e)+" is not iterable")}return g.prototype=w,o(T,"constructor",{value:w,configurable:!0}),o(w,"constructor",{value:g,configurable:!0}),g.displayName=l(w,u,"GeneratorFunction"),e.isGeneratorFunction=function(t){var e="function"==typeof t&&t.constructor;return!!e&&(e===g||"GeneratorFunction"===(e.displayName||e.name))},e.mark=function(t){return Object.setPrototypeOf?Object.setPrototypeOf(t,w):(t.__proto__=w,l(t,u,"GeneratorFunction")),t.prototype=Object.create(T),t},e.awrap=function(t){return{__await:t}},_(L.prototype),l(L.prototype,c,(function(){return this})),e.AsyncIterator=L,e.async=function(t,r,n,o,i){void 0===i&&(i=Promise);var a=new L(f(t,r,n,o),i);return e.isGeneratorFunction(r)?a:a.next().then((function(t){return t.done?t.value:a.next()}))},_(T),l(T,u,"Generator"),l(T,a,(function(){return this})),l(T,"toString",(function(){return"[object Generator]"})),e.keys=function(t){var e=Object(t),r=[];for(var n in e)r.push(n);return r.reverse(),function t(){for(;r.length;){var n=r.pop();if(n in e)return t.value=n,t.done=!1,t}return t.done=!0,t}},e.values=B,G.prototype={constructor:G,reset:function(e){if(this.prev=0,this.next=0,this.sent=this._sent=t,this.done=!1,this.delegate=null,this.method="next",this.arg=t,this.tryEntries.forEach(j),!e)for(var r in this)"t"===r.charAt(0)&&n.call(this,r)&&!isNaN(+r.slice(1))&&(this[r]=t)},stop:function(){this.done=!0;var t=this.tryELine truncated
|
||||
@@ -1 +0,0 @@
|
||||
/*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */
|
||||
@@ -1,80 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
|
||||
* See LICENSE in the project root for license information.
|
||||
*/
|
||||
|
||||
html,
|
||||
body {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
ul {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.ms-welcome__header {
|
||||
padding: 20px;
|
||||
padding-bottom: 30px;
|
||||
padding-top: 100px;
|
||||
display: -webkit-flex;
|
||||
display: flex;
|
||||
-webkit-flex-direction: column;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.ms-welcome__main {
|
||||
display: -webkit-flex;
|
||||
display: flex;
|
||||
-webkit-flex-direction: column;
|
||||
flex-direction: column;
|
||||
-webkit-flex-wrap: nowrap;
|
||||
flex-wrap: nowrap;
|
||||
-webkit-align-items: center;
|
||||
align-items: center;
|
||||
-webkit-flex: 1 0 0;
|
||||
flex: 1 0 0;
|
||||
padding: 10px 20px;
|
||||
}
|
||||
|
||||
.ms-welcome__main > h2 {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.ms-welcome__features {
|
||||
list-style-type: none;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.ms-welcome__features.ms-List .ms-ListItem {
|
||||
padding-bottom: 20px;
|
||||
display: -webkit-flex;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.ms-welcome__features.ms-List .ms-ListItem > .ms-Icon {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.ms-welcome__action.ms-Button--hero {
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
.ms-Button.ms-Button--hero .ms-Button-label {
|
||||
color: #0078d7;
|
||||
}
|
||||
|
||||
.ms-Button.ms-Button--hero:hover .ms-Button-label,
|
||||
.ms-Button.ms-Button--hero:focus .ms-Button-label{
|
||||
color: #005a9e;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
b {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
Before Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 839 B |
|
Before Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 8.8 KiB |
|
Before Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 99 KiB |
@@ -1 +0,0 @@
|
||||
<!doctype html><html><head><meta charset="UTF-8"/><meta http-equiv="X-UA-Compatible" content="IE=Edge"/><script src="https://appsforoffice.microsoft.com/lib/1.1/hosted/office.js"></script><script defer="defer" src="polyfill.js"></script><script defer="defer" src="commands.js"></script></head><body></body></html>
|
||||
@@ -1,2 +0,0 @@
|
||||
!function(){var e={};e.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),Office.onReady((function(){})),("undefined"!=typeof self?self:"undefined"!=typeof window?window:void 0!==e.g?e.g:void 0).action=function(e){var n={type:Office.MailboxEnums.ItemNotificationMessageType.InformationalMessage,message:"Performed action.",icon:"Icon.80x80",persistent:!0};Office.context.mailbox.item.notificationMessages.replaceAsync("action",n),e.completed()}}();
|
||||
//# sourceMappingURL=commands.js.map
|
||||
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"commands.js","mappings":"YACA,IAAIA,EAAsB,CAAC,ECD3BA,EAAoBC,EAAI,WACvB,GAA0B,iBAAfC,WAAyB,OAAOA,WAC3C,IACC,OAAOC,MAAQ,IAAIC,SAAS,cAAb,EAChB,CAAE,MAAOC,GACR,GAAsB,iBAAXC,OAAqB,OAAOA,MACxC,CACA,CAPuB,GCOxBC,OAAOC,SAAQ,WACb,KAuBuB,oBAATC,KACVA,KACkB,oBAAXH,OACPA,YACkB,IAAXI,EAAAA,EACPA,EAAAA,OACAC,GAMJC,OA5BF,SAAgBC,GACd,IAAMC,EAAU,CACdC,KAAMR,OAAOS,aAAaC,4BAA4BC,qBACtDJ,QAAS,oBACTK,KAAM,aACNC,YAAY,GAIdb,OAAOc,QAAQC,QAAQC,KAAKC,qBAAqBC,aAAa,SAAUX,GAGxED,EAAMa,WACR,C","sources":["webpack://office-addin-taskpane-js/webpack/bootstrap","webpack://office-addin-taskpane-js/webpack/runtime/global","webpack://office-addin-taskpane-js/./src/commands/commands.js"],"sourcesContent":["// The require scope\nvar __webpack_require__ = {};\n\n","__webpack_require__.g = (function() {\n\tif (typeof globalThis === 'object') return globalThis;\n\ttry {\n\t\treturn this || new Function('return this')();\n\t} catch (e) {\n\t\tif (typeof window === 'object') return window;\n\t}\n})();","/*\n * Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n * See LICENSE in the project root for license information.\n */\n\n/* global global, Office, self, window */\n\nOffice.onReady(() => {\n // If needed, Office.js is ready to be called\n});\n\n/**\n * Shows a notification when the add-in command is executed.\n * @param event {Office.AddinCommands.Event}\n */\nfunction action(event) {\n const message = {\n type: Office.MailboxEnums.ItemNotificationMessageType.InformationalMessage,\n message: \"Performed action.\",\n icon: \"Icon.80x80\",\n persistent: true,\n };\n\n // Show a notification message\n Office.context.mailbox.item.notificationMessages.replaceAsync(\"action\", message);\n\n // Be sure to indicate when the add-in command function is complete\n event.completed();\n}\n\nfunction getGlobal() {\n return typeof self !== \"undefined\"\n ? self\n : typeof window !== \"undefined\"\n ? window\n : typeof global !== \"undefined\"\n ? global\n : undefined;\n}\n\nconst g = getGlobal();\n\n// The add-in command functions need to be available in global scope\ng.action = action;\n"],"names":["__webpack_require__","g","globalThis","this","Function","e","window","Office","onReady","self","global","undefined","action","event","message","type","MailboxEnums","ItemNotificationMessageType","InformationalMessage","icon","persistent","context","mailbox","item","notificationMessages","replaceAsync","completed"],"sourceRoot":""}
|
||||
@@ -1,79 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<OfficeApp xmlns="http://schemas.microsoft.com/office/appforoffice/1.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:bt="http://schemas.microsoft.com/office/officeappbasictypes/1.0" xmlns:ov="http://schemas.microsoft.com/office/taskpaneappversionoverrides" xsi:type="TaskPaneApp">
|
||||
<Id>68b6ad53-4f72-42a8-a971-a9643c2f409a</Id>
|
||||
<Version>1.0.0.0</Version>
|
||||
<ProviderName>AllTalk</ProviderName>
|
||||
<DefaultLocale>en-US</DefaultLocale>
|
||||
<DisplayName DefaultValue="AllTalk TTS"/>
|
||||
<Description DefaultValue="Enhance your document creation with AllTalk TTS's advanced text-to-voice functionality. Requires connection to AllTalk server."/>
|
||||
<IconUrl DefaultValue="http://127.0.0.1:7851/api/word_addin/assets/icon-32.png"/>
|
||||
<HighResolutionIconUrl DefaultValue="http://127.0.0.1:7851/api/word_addin/assets/icon-64.png"/>
|
||||
<SupportUrl DefaultValue="https://github.com/erew123/alltalk_tts/issues"/>
|
||||
<AppDomains>
|
||||
<AppDomain>https://www.contoso.com</AppDomain>
|
||||
</AppDomains>
|
||||
<Hosts>
|
||||
<Host Name="Document"/>
|
||||
</Hosts>
|
||||
<DefaultSettings>
|
||||
<SourceLocation DefaultValue="http://127.0.0.1:7851/api/word_addin/taskpane.html"/>
|
||||
</DefaultSettings>
|
||||
<Permissions>ReadWriteDocument</Permissions>
|
||||
<VersionOverrides xmlns="http://schemas.microsoft.com/office/taskpaneappversionoverrides" xsi:type="VersionOverridesV1_0">
|
||||
<Hosts>
|
||||
<Host xsi:type="Document">
|
||||
<DesktopFormFactor>
|
||||
<!-- You can add GetStarted information here if needed -->
|
||||
<FunctionFile resid="Commands.Url"/>
|
||||
<ExtensionPoint xsi:type="PrimaryCommandSurface">
|
||||
<OfficeTab id="TabHome">
|
||||
<Group id="AllTalkGroup">
|
||||
<Label resid="AllTalkGroup.Label"/>
|
||||
<Icon>
|
||||
<bt:Image size="16" resid="Icon.16x16"/>
|
||||
<bt:Image size="32" resid="Icon.32x32"/>
|
||||
<bt:Image size="80" resid="Icon.80x80"/>
|
||||
</Icon>
|
||||
<Control xsi:type="Button" id="AllTalkTaskpaneButton">
|
||||
<Label resid="AllTalkTaskpaneButton.Label"/>
|
||||
<Supertip>
|
||||
<Title resid="AllTalkTaskpaneButton.Label"/>
|
||||
<Description resid="AllTalkTaskpaneButton.Tooltip"/>
|
||||
</Supertip>
|
||||
<Icon>
|
||||
<bt:Image size="16" resid="Icon.16x16"/>
|
||||
<bt:Image size="32" resid="Icon.32x32"/>
|
||||
<bt:Image size="80" resid="Icon.80x80"/>
|
||||
</Icon>
|
||||
<Action xsi:type="ShowTaskpane">
|
||||
<TaskpaneId>ButtonId1</TaskpaneId>
|
||||
<SourceLocation resid="Taskpane.Url"/>
|
||||
</Action>
|
||||
</Control>
|
||||
</Group>
|
||||
</OfficeTab>
|
||||
</ExtensionPoint>
|
||||
</DesktopFormFactor>
|
||||
</Host>
|
||||
</Hosts>
|
||||
<Resources>
|
||||
<bt:Images>
|
||||
<bt:Image id="Icon.16x16" DefaultValue="http://127.0.0.1:7851/api/word_addin/assets/icon-16.png"/>
|
||||
<bt:Image id="Icon.32x32" DefaultValue="http://127.0.0.1:7851/api/word_addin/assets/icon-32.png"/>
|
||||
<bt:Image id="Icon.80x80" DefaultValue="http://127.0.0.1:7851/api/word_addin/assets/icon-80.png"/>
|
||||
</bt:Images>
|
||||
<bt:Urls>
|
||||
<!-- Ensure that these URLs are pointing to valid locations -->
|
||||
<bt:Url id="Commands.Url" DefaultValue="http://127.0.0.1:7851/api/word_addin/commands.html"/>
|
||||
<bt:Url id="Taskpane.Url" DefaultValue="http://127.0.0.1:7851/api/word_addin/taskpane.html"/>
|
||||
</bt:Urls>
|
||||
<bt:ShortStrings>
|
||||
<bt:String id="AllTalkGroup.Label" DefaultValue="AllTalk Controls"/>
|
||||
<bt:String id="AllTalkTaskpaneButton.Label" DefaultValue="Open AllTalk"/>
|
||||
</bt:ShortStrings>
|
||||
<bt:LongStrings>
|
||||
<bt:String id="AllTalkTaskpaneButton.Tooltip" DefaultValue="Open the AllTalk task pane to start using the add-in."/>
|
||||
</bt:LongStrings>
|
||||
</Resources>
|
||||
</VersionOverrides>
|
||||
</OfficeApp>
|
||||
@@ -1,2 +0,0 @@
|
||||
!function(){var t={35666:function(t){var r=function(t){"use strict";var r,e=Object.prototype,n=e.hasOwnProperty,i=Object.defineProperty||function(t,r,e){t[r]=e.value},o="function"==typeof Symbol?Symbol:{},u=o.iterator||"@@iterator",a=o.asyncIterator||"@@asyncIterator",c=o.toStringTag||"@@toStringTag";function s(t,r,e){return Object.defineProperty(t,r,{value:e,enumerable:!0,configurable:!0,writable:!0}),t[r]}try{s({},"")}catch(t){s=function(t,r,e){return t[r]=e}}function f(t,r,e,n){var o=r&&r.prototype instanceof y?r:y,u=Object.create(o.prototype),a=new j(n||[]);return i(u,"_invoke",{value:R(t,e,a)}),u}function l(t,r,e){try{return{type:"normal",arg:t.call(r,e)}}catch(t){return{type:"throw",arg:t}}}t.wrap=f;var h="suspendedStart",p="suspendedYield",v="executing",g="completed",d={};function y(){}function m(){}function b(){}var x={};s(x,u,(function(){return this}));var w=Object.getPrototypeOf,E=w&&w(w(P([])));E&&E!==e&&n.call(E,u)&&(x=E);var S=b.prototype=y.prototype=Object.create(x);function A(t){["next","throw","return"].forEach((function(r){s(t,r,(function(t){return this._invoke(r,t)}))}))}function O(t,r){function e(i,o,u,a){var c=l(t[i],t,o);if("throw"!==c.type){var s=c.arg,f=s.value;return f&&"object"==typeof f&&n.call(f,"__await")?r.resolve(f.__await).then((function(t){e("next",t,u,a)}),(function(t){e("throw",t,u,a)})):r.resolve(f).then((function(t){s.value=t,u(s)}),(function(t){return e("throw",t,u,a)}))}a(c.arg)}var o;i(this,"_invoke",{value:function(t,n){function i(){return new r((function(r,i){e(t,n,r,i)}))}return o=o?o.then(i,i):i()}})}function R(t,r,e){var n=h;return function(i,o){if(n===v)throw new Error("Generator is already running");if(n===g){if("throw"===i)throw o;return k()}for(e.method=i,e.arg=o;;){var u=e.delegate;if(u){var a=T(u,e);if(a){if(a===d)continue;return a}}if("next"===e.method)e.sent=e._sent=e.arg;else if("throw"===e.method){if(n===h)throw n=g,e.arg;e.dispatchException(e.arg)}else"return"===e.method&&e.abrupt("return",e.arg);n=v;var c=l(t,r,e);if("normal"===c.type){if(n=e.done?g:p,c.arg===d)continue;return{value:c.arg,done:e.done}}"throw"===c.type&&(n=g,e.method="throw",e.arg=c.arg)}}}function T(t,e){var n=e.method,i=t.iterator[n];if(i===r)return e.delegate=null,"throw"===n&&t.iterator.return&&(e.method="return",e.arg=r,T(t,e),"throw"===e.method)||"return"!==n&&(e.method="throw",e.arg=new TypeError("The iterator does not provide a '"+n+"' method")),d;var o=l(i,t.iterator,e.arg);if("throw"===o.type)return e.method="throw",e.arg=o.arg,e.delegate=null,d;var u=o.arg;return u?u.done?(e[t.resultName]=u.value,e.next=t.nextLoc,"return"!==e.method&&(e.method="next",e.arg=r),e.delegate=null,d):u:(e.method="throw",e.arg=new TypeError("iterator result is not an object"),e.delegate=null,d)}function I(t){var r={tryLoc:t[0]};1 in t&&(r.catchLoc=t[1]),2 in t&&(r.finallyLoc=t[2],r.afterLoc=t[3]),this.tryEntries.push(r)}function M(t){var r=t.completion||{};r.type="normal",delete r.arg,t.completion=r}function j(t){this.tryEntries=[{tryLoc:"root"}],t.forEach(I,this),this.reset(!0)}function P(t){if(t){var e=t[u];if(e)return e.call(t);if("function"==typeof t.next)return t;if(!isNaN(t.length)){var i=-1,o=function e(){for(;++i<t.length;)if(n.call(t,i))return e.value=t[i],e.done=!1,e;return e.value=r,e.done=!0,e};return o.next=o}}return{next:k}}function k(){return{value:r,done:!0}}return m.prototype=b,i(S,"constructor",{value:b,configurable:!0}),i(b,"constructor",{value:m,configurable:!0}),m.displayName=s(b,c,"GeneratorFunction"),t.isGeneratorFunction=function(t){var r="function"==typeof t&&t.constructor;return!!r&&(r===m||"GeneratorFunction"===(r.displayName||r.name))},t.mark=function(t){return Object.setPrototypeOf?Object.setPrototypeOf(t,b):(t.__proto__=b,s(t,c,"GeneratorFunction")),t.prototype=Object.create(S),t},t.awrap=function(t){return{__await:t}},A(O.prototype),s(O.prototype,a,(function(){return this})),t.AsyncIterator=O,t.async=function(r,e,n,i,o){void 0===o&&(o=Promise);var u=new O(f(r,e,n,i),o);return t.isGeneratorFunction(e)?u:u.next().then((function(t){return t.done?t.value:u.next()}))},A(S),s(S,c,"Generator"),s(S,u,(function(){return this})),s(S,"toString",(function(){return"[object Generator]"})),t.keys=function(t){var r=Object(t),e=[];for(var n in r)e.push(n);return e.reverse(),function t(){for(;e.length;){var n=e.pop();if(n in r)return t.value=n,t.done=!1,t}return t.done=!0,t}},t.values=P,j.prototype={constructor:j,reset:function(t){if(this.prev=0,this.next=0,this.sent=this._sent=r,this.done=!1,this.delegate=null,this.method="next",this.arg=r,this.tryEntries.forEach(M),!t)for(var e in this)"t"===e.charAt(0)&&n.call(this,e)&&!isNaN(+e.slice(1))&&(this[e]=r)},stop:function(){this.done=!0;var t=this.tryEntries[0].completion;if("throw"===t.type)throw t.arg;return this.rval},dispatchException:function(t){if(this.done)throw t;var e=this;function i(n,i){return a.type="throw",a.arg=t,e.next=n,i&&(e.method="next",e.arg=r),!!i}for(var o=this.tryEntries.length-1;o>=0;--o){var u=this.tryEntries[o],aLine truncated
|
||||
//# sourceMappingURL=polyfill.js.map
|
||||
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"polyfill.js","mappings":"qCAOA,IAAIA,EAAW,SAAUC,GACvB,aAEA,IAGIC,EAHAC,EAAKC,OAAOC,UACZC,EAASH,EAAGI,eACZC,EAAiBJ,OAAOI,gBAAkB,SAAUC,EAAKC,EAAKC,GAAQF,EAAIC,GAAOC,EAAKC,KAAO,EAE7FC,EAA4B,mBAAXC,OAAwBA,OAAS,CAAC,EACnDC,EAAiBF,EAAQG,UAAY,aACrCC,EAAsBJ,EAAQK,eAAiB,kBAC/CC,EAAoBN,EAAQO,aAAe,gBAE/C,SAASC,EAAOZ,EAAKC,EAAKE,GAOxB,OANAR,OAAOI,eAAeC,EAAKC,EAAK,CAC9BE,MAAOA,EACPU,YAAY,EACZC,cAAc,EACdC,UAAU,IAELf,EAAIC,EACb,CACA,IAEEW,EAAO,CAAC,EAAG,GACb,CAAE,MAAOI,GACPJ,EAAS,SAASZ,EAAKC,EAAKE,GAC1B,OAAOH,EAAIC,GAAOE,CACpB,CACF,CAEA,SAASc,EAAKC,EAASC,EAASC,EAAMC,GAEpC,IAAIC,EAAiBH,GAAWA,EAAQvB,qBAAqB2B,EAAYJ,EAAUI,EAC/EC,EAAY7B,OAAO8B,OAAOH,EAAe1B,WACzC8B,EAAU,IAAIC,EAAQN,GAAe,IAMzC,OAFAtB,EAAeyB,EAAW,UAAW,CAAErB,MAAOyB,EAAiBV,EAASE,EAAMM,KAEvEF,CACT,CAaA,SAASK,EAASC,EAAI9B,EAAK+B,GACzB,IACE,MAAO,CAAEC,KAAM,SAAUD,IAAKD,EAAGG,KAAKjC,EAAK+B,GAC7C,CAAE,MAAOf,GACP,MAAO,CAAEgB,KAAM,QAASD,IAAKf,EAC/B,CACF,CAlBAxB,EAAQyB,KAAOA,EAoBf,IAAIiB,EAAyB,iBACzBC,EAAyB,iBACzBC,EAAoB,YACpBC,EAAoB,YAIpBC,EAAmB,CAAC,EAMxB,SAASf,IAAa,CACtB,SAASgB,IAAqB,CAC9B,SAASC,IAA8B,CAIvC,IAAIC,EAAoB,CAAC,EACzB7B,EAAO6B,EAAmBnC,GAAgB,WACxC,OAAOoC,IACT,IAEA,IAAIC,EAAWhD,OAAOiD,eAClBC,EAA0BF,GAAYA,EAASA,EAASG,EAAO,MAC/DD,GACAA,IAA4BnD,GAC5BG,EAAOoC,KAAKY,EAAyBvC,KAGvCmC,EAAoBI,GAGtB,IAAIE,EAAKP,EAA2B5C,UAClC2B,EAAU3B,UAAYD,OAAO8B,OAAOgB,GAgBtC,SAASO,EAAsBpD,GAC7B,CAAC,OAAQ,QAAS,UAAUqD,SAAQ,SAASC,GAC3CtC,EAAOhB,EAAWsD,GAAQ,SAASnB,GACjC,OAAOW,KAAKS,QAAQD,EAAQnB,EAC9B,GACF,GACF,CA+BA,SAASqB,EAAc5B,EAAW6B,GAChC,SAASC,EAAOJ,EAAQnB,EAAKwB,EAASC,GACpC,IAAIC,EAAS5B,EAASL,EAAU0B,GAAS1B,EAAWO,GACpD,GAAoB,UAAhB0B,EAAOzB,KAEJ,CACL,IAAI0B,EAASD,EAAO1B,IAChB5B,EAAQuD,EAAOvD,MACnB,OAAIA,GACiB,iBAAVA,GACPN,EAAOoC,KAAK9B,EAAO,WACdkD,EAAYE,QAAQpD,EAAMwD,SAASC,MAAK,SAASzD,GACtDmD,EAAO,OAAQnD,EAAOoD,EAASC,EACjC,IAAG,SAASxC,GACVsC,EAAO,QAAStC,EAAKuC,EAASC,EAChC,IAGKH,EAAYE,QAAQpD,GAAOyD,MAAK,SAASC,GAI9CH,EAAOvD,MAAQ0D,EACfN,EAAQG,EACV,IAAG,SAASI,GAGV,OAAOR,EAAO,QAASQ,EAAOP,EAASC,EACzC,GACF,CAzBEA,EAAOC,EAAO1B,IA0BlB,CAEA,IAAIgC,EAgCJhE,EAAe2C,KAAM,UAAW,CAAEvC,MA9BlC,SAAiB+C,EAAQnB,GACvB,SAASiC,IACP,OAAO,IAAIX,GAAY,SAASE,EAASC,GACvCF,EAAOJ,EAAQnB,EAAKwB,EAASC,EAC/B,GACF,CAEA,OAAOO,EAaLA,EAAkBA,EAAgBH,KAChCI,EAGAA,GACEA,GACR,GAKF,CA0BA,SAASpC,EAAiBV,EAASE,EAAMM,GACvC,IAAIuC,EAAQ/B,EAEZ,OAAO,SAAgBgB,EAAQnB,GAC7B,GAAIkC,IAAU7B,EACZ,MAAM,IAAI8B,MAAM,gCAGlB,GAAID,IAAU5B,EAAmB,CAC/B,GAAe,UAAXa,EACF,MAAMnB,EAKR,OAAOoC,GACT,CAKA,IAHAzC,EAAQwB,OAASA,EACjBxB,EAAQK,IAAMA,IAED,CACX,IAAIqC,EAAW1C,EAAQ0C,SACvB,GAAIA,EAAU,CACZ,IAAIC,EAAiBC,EAAoBF,EAAU1C,GACnD,GAAI2C,EAAgB,CAClB,GAAIA,IAAmB/B,EAAkB,SACzC,OAAO+B,CACT,CACF,CAEA,GAAuB,SAAnB3C,EAAQwB,OAGVxB,EAAQ6C,KAAO7C,EAAQ8C,MAAQ9C,EAAQK,SAElC,GAAuB,UAAnBL,EAAQwB,OAAoB,CACrC,GAAIe,IAAU/B,EAEZ,MADA+B,EAAQ5B,EACFX,EAAQK,IAGhBL,EAAQ+C,kBAAkB/C,EAAQK,IAEpC,KAA8B,WAAnBL,EAAQwB,QACjBxB,EAAQgD,OAAO,SAAUhD,EAAQK,KAGnCkC,EAAQ7B,EAER,IAAIqB,EAAS5B,EAASX,EAASE,EAAMM,GACrC,GAAoB,WAAhB+B,EAAOzB,KAAmB,CAO5B,GAJAiC,EAAQvC,EAAQiD,KACZtC,EACAF,EAEAsB,EAAO1B,MAAQO,EACjB,SAGF,MAAO,CACLnC,MAAOsD,EAAO1B,IACd4C,KAAMjD,EAAQiD,KAGlB,CAA2B,UAAhBlB,EAAOzB,OAChBiC,EAAQ5B,EAGRX,EAAQwB,OAAS,QACjBxB,EAAQK,IAAM0B,EAAO1B,IAEzB,CACF,CACF,CAMA,SAASuC,EAAoBF,EAAU1C,GACrC,IAAIkD,EAAalD,EAAQwB,OACrBA,EAASkB,EAAS7D,SAASqE,GAC/B,GAAI1B,IAAWzD,EAOb,OAHAiC,EAAQ0C,SAAW,KAGA,UAAfQ,GAA0BR,EAAS7D,SAAiB,SAGtDmB,EAAQwB,OAAS,SACjBxB,EAAQK,IAAMtC,EACd6E,EAAoBF,EAAU1C,GAEP,UAAnBA,EAAQwB,SAMK,WAAf0B,IACFlD,EAAQwB,OAAS,QACjBxB,EAAQK,IAAM,IAAI8C,UAChB,oCAAsCD,EAAa,aAN5CtC,EAYb,IAAImB,EAAS5B,EAASqB,EAAQkB,EAAS7D,SAAUmB,EAAQK,KAEzD,GAAoB,UAAhB0B,EAAOzB,KAIT,OAHAN,EAAQwB,OAAS,QACjBxB,EAAQK,IAAM0B,EAAO1B,IACrBL,EAAQ0C,SAAW,KACZ9B,EAGT,IAAIwC,EAAOrB,EAAO1B,IAElB,OAAM+C,EAOFA,EAAKH,MAGPjD,EAAQ0C,EAASW,YAAcD,EAAK3E,MAGpCuB,EAAQsD,KAAOZ,EAASa,QAQD,WAAnBvD,EAAQwB,SACVxB,EAAQwB,OAAS,OACjBxB,EAAQK,IAAMtC,GAUlBiC,EAAQ0C,SAAW,KACZ9B,GANEwC,GA3BPpD,EAAQwB,OAAS,QACjBxB,EAAQK,IAAM,IAAI8C,UAAU,oCAC5BnD,EAAQ0C,SAAW,KACZ9B,EA+BX,CAqBA,SAAS4C,EAAaC,GACpB,IAAIC,EAAQ,CAAEC,OAAQF,EAAK,IAEvB,KAAKA,IACPC,EAAME,SAAWH,EAAK,IAGpB,KAAKA,IACPC,EAAMG,WAAaJ,EAAK,GACxBC,EAAMI,SAAWL,EAAK,IAGxBzC,KAAK+C,WAAWC,KAAKN,EACvB,CAEA,SAASO,EAAcP,GACrB,IAAI3B,EAAS2B,EAAMQ,YAAc,CAAC,EAClCnC,EAAOzB,KAAO,gBACPyB,EAAO1B,IACdqD,EAAMQ,WAAanC,CACrB,CAEA,SAAS9B,EAAQN,GAIfqB,KAAK+C,WAAa,CAAC,CAAEJ,OAAQ,SAC7BhE,EAAY4B,QAAQiC,EAAcxC,MAClCA,KAAKmD,OAAM,EACb,CA8BA,SAAS/C,EAAOgD,GACd,GAAIA,EAAU,CACZ,IAAIC,EAAiBD,EAASxF,GAC9B,GAAIyF,EACF,OAAOA,EAAe9D,KAAK6D,GAG7B,GAA6B,mBAAlBA,EAASd,KAClB,OAAOc,EAGT,IAAKE,MAAMF,EAASG,QAAS,CAC3B,IAAIC,GAAK,EAAGlB,EAAO,SAASA,IAC1B,OAASkB,EAAIJ,EAASG,QACpB,GAAIpG,EAAOoC,KAAK6D,EAAUI,GAGxB,OAFAlB,EAAK7E,MAAQ2F,EAASI,GACtBlB,EAAKL,MAAO,EACLK,EAOX,OAHAA,EAAK7E,MAAQV,EACbuF,EAAKL,MAAO,EAELK,CACT,EAEA,OAAOA,EAAKA,KAAOA,CACrB,CACF,CAGA,MAAO,CAAEA,KAAMb,EACjB,CAGA,SAASA,IACP,MAAO,CAAEhE,MAAOV,EAAWkF,MAAM,EACnC,CA8MA,OAnnBApC,EAAkB3C,UAAY4C,EAC9BzC,EAAegD,EAAI,cAAe,CAAE5C,MAAOqC,EAA4B1B,cAAc,IACrFf,EACEyC,EACA,cACA,CAAErC,MAAOoC,EAAmBzB,cAAc,IAE5CyB,EAAkB4D,YAAcvF,EAC9B4B,EACA9B,EACA,qBAaFlB,EAAQ4G,oBAAsB,SLine truncated
|
||||
@@ -1,106 +0,0 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=Edge" />
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<title>AllTalk TTS Add-in</title>
|
||||
<script src="https://appsforoffice.microsoft.com/lib/1.1/hosted/office.js"></script>
|
||||
<link rel="stylesheet"
|
||||
href="https://static2.sharepointonline.com/files/fabric/office-ui-fabric-core/11.0.0/css/fabric.min.css" />
|
||||
<link href="1fda685b81e1123773f6.css" rel="stylesheet" />
|
||||
<style>
|
||||
label {
|
||||
font-weight: 700;
|
||||
display: block;
|
||||
margin-top: 10px
|
||||
}
|
||||
|
||||
select {
|
||||
width: 100%;
|
||||
padding: 5px
|
||||
}
|
||||
|
||||
.nice-button {
|
||||
background-color: #0078d4;
|
||||
color: #fff;
|
||||
padding: 10px 20px;
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
font-size: 16px;
|
||||
transition: background-color .3s ease
|
||||
}
|
||||
|
||||
.nice-button:hover {
|
||||
background-color: #005a9e
|
||||
}
|
||||
|
||||
#audioSource {
|
||||
width: 300px;
|
||||
height: 50px
|
||||
}
|
||||
|
||||
.input-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-right: 10px
|
||||
}
|
||||
|
||||
.input-group {
|
||||
display: flex;
|
||||
justify-content: start;
|
||||
align-items: flex-end
|
||||
}
|
||||
|
||||
.input-group>.input-container {
|
||||
flex: 1
|
||||
}
|
||||
|
||||
input {
|
||||
width: 100%
|
||||
}
|
||||
</style>
|
||||
<script defer="defer" src="polyfill.js"></script>
|
||||
<script defer="defer" src="taskpane.js"></script>
|
||||
</head>
|
||||
|
||||
<body class="ms-font-m ms-welcome ms-Fabric">
|
||||
<header class="ms-welcome__header ms-bgColor-neutralLighter"><img width="90" height="90"
|
||||
src="http://127.0.0.1:7851/api/word_addin/assets/logo-filled.png" alt="AllTalk TTS" title="AllTalk TTS" />
|
||||
<h1 class="ms-font-su">AllTalk TTS</h1>
|
||||
</header>
|
||||
<main class="ms-welcome__main"><textarea id="text" rows="4" placeholder="Enter text here"
|
||||
style="display:none"></textarea> <label for="voice">Voice:</label> <select id="voice" name="voice"
|
||||
required></select> <label for="language">Language:</label> <select id="language" name="language"
|
||||
value="English" required>
|
||||
<option value="en" selected="selected">English</option>
|
||||
<option value="ar">Arabic</option>
|
||||
<option value="zh-cn">Chinese</option>
|
||||
<option value="cs">Czech</option>
|
||||
<option value="nl">Dutch</option>
|
||||
<option value="fr">French</option>
|
||||
<option value="de">German</option>
|
||||
<option value="hu">Hungarian</option>
|
||||
<option value="it">Italian</option>
|
||||
<option value="ja">Japanese</option>
|
||||
<option value="ko">Korean</option>
|
||||
<option value="pl">Polish</option>
|
||||
<option value="pt">Portuguese</option>
|
||||
<option value="ru">Russian</option>
|
||||
<option value="es">Spanish</option>
|
||||
<option value="tr">Turkish</option>
|
||||
</select><br><audio id="audioSource" controls autoplay></audio><br><button id="sendTextButton"
|
||||
class="nice-button">Send Text to TTS</button><br><br><br><br>
|
||||
<div class="input-group">
|
||||
<div class="input-container"><label for="serverIP">Server IP:</label> <input id="serverIP" name="serverIP"
|
||||
value="127.0.0.1" required></div>
|
||||
<div class="input-container"><label for="portNumber">Port Number:</label> <input type="number"
|
||||
id="portNumber" name="portNumber" value="7851" required></div>
|
||||
</div>
|
||||
</main>
|
||||
<script src="1995fcd6d39cade7d871.js"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -1,3 +0,0 @@
|
||||
/*! For license information please see taskpane.js.LICENSE.txt */
|
||||
!function(){var t={27091:function(t){"use strict";t.exports=function(t,e){return e||(e={}),t?(t=String(t.__esModule?t.default:t),e.hash&&(t+=e.hash),e.maybeNeedQuotes&&/[\t\n\f\r "'=<>`]/.test(t)?'"'.concat(t,'"'):t):t}},44944:function(t,e,r){"use strict";t.exports=r.p+"assets/logo-filled.png"},36076:function(t,e,r){"use strict";t.exports=r.p+"1995fcd6d39cade7d871.js"},60806:function(t,e,r){"use strict";t.exports=r.p+"1fda685b81e1123773f6.css"}},e={};function r(n){var o=e[n];if(void 0!==o)return o.exports;var i=e[n]={exports:{}};return t[n](i,i.exports,r),i.exports}r.m=t,r.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return r.d(e,{a:e}),e},r.d=function(t,e){for(var n in e)r.o(e,n)&&!r.o(t,n)&&Object.defineProperty(t,n,{enumerable:!0,get:e[n]})},r.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(t){if("object"==typeof window)return window}}(),r.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},function(){var t;r.g.importScripts&&(t=r.g.location+"");var e=r.g.document;if(!t&&e&&(e.currentScript&&(t=e.currentScript.src),!t)){var n=e.getElementsByTagName("script");if(n.length)for(var o=n.length-1;o>-1&&!t;)t=n[o--].src}if(!t)throw new Error("Automatic publicPath is not supported in this browser");t=t.replace(/#.*$/,"").replace(/\?.*$/,"").replace(/\/[^\/]+$/,"/"),r.p=t}(),r.b=document.baseURI||self.location.href,function(){function t(e){return t="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},t(e)}function e(){"use strict";e=function(){return n};var r,n={},o=Object.prototype,i=o.hasOwnProperty,c=Object.defineProperty||function(t,e,r){t[e]=r.value},a="function"==typeof Symbol?Symbol:{},u=a.iterator||"@@iterator",f=a.asyncIterator||"@@asyncIterator",s=a.toStringTag||"@@toStringTag";function l(t,e,r){return Object.defineProperty(t,e,{value:r,enumerable:!0,configurable:!0,writable:!0}),t[e]}try{l({},"")}catch(r){l=function(t,e,r){return t[e]=r}}function h(t,e,r,n){var o=e&&e.prototype instanceof w?e:w,i=Object.create(o.prototype),a=new k(n||[]);return c(i,"_invoke",{value:I(t,r,a)}),i}function p(t,e,r){try{return{type:"normal",arg:t.call(e,r)}}catch(t){return{type:"throw",arg:t}}}n.wrap=h;var y="suspendedStart",v="suspendedYield",d="executing",m="completed",g={};function w(){}function b(){}function x(){}var E={};l(E,u,(function(){return this}));var L=Object.getPrototypeOf,_=L&&L(L(T([])));_&&_!==o&&i.call(_,u)&&(E=_);var j=x.prototype=w.prototype=Object.create(E);function O(t){["next","throw","return"].forEach((function(e){l(t,e,(function(t){return this._invoke(e,t)}))}))}function S(e,r){function n(o,c,a,u){var f=p(e[o],e,c);if("throw"!==f.type){var s=f.arg,l=s.value;return l&&"object"==t(l)&&i.call(l,"__await")?r.resolve(l.__await).then((function(t){n("next",t,a,u)}),(function(t){n("throw",t,a,u)})):r.resolve(l).then((function(t){s.value=t,a(s)}),(function(t){return n("throw",t,a,u)}))}u(f.arg)}var o;c(this,"_invoke",{value:function(t,e){function i(){return new r((function(r,o){n(t,e,r,o)}))}return o=o?o.then(i,i):i()}})}function I(t,e,n){var o=y;return function(i,c){if(o===d)throw new Error("Generator is already running");if(o===m){if("throw"===i)throw c;return{value:r,done:!0}}for(n.method=i,n.arg=c;;){var a=n.delegate;if(a){var u=P(a,n);if(u){if(u===g)continue;return u}}if("next"===n.method)n.sent=n._sent=n.arg;else if("throw"===n.method){if(o===y)throw o=m,n.arg;n.dispatchException(n.arg)}else"return"===n.method&&n.abrupt("return",n.arg);o=d;var f=p(t,e,n);if("normal"===f.type){if(o=n.done?m:v,f.arg===g)continue;return{value:f.arg,done:n.done}}"throw"===f.type&&(o=m,n.method="throw",n.arg=f.arg)}}}function P(t,e){var n=e.method,o=t.iterator[n];if(o===r)return e.delegate=null,"throw"===n&&t.iterator.return&&(e.method="return",e.arg=r,P(t,e),"throw"===e.method)||"return"!==n&&(e.method="throw",e.arg=new TypeError("The iterator does not provide a '"+n+"' method")),g;var i=p(o,t.iterator,e.arg);if("throw"===i.type)return e.method="throw",e.arg=i.arg,e.delegate=null,g;var c=i.arg;return c?c.done?(e[t.resultName]=c.value,e.next=t.nextLoc,"return"!==e.method&&(e.method="next",e.arg=r),e.delegate=null,g):c:(e.method="throw",e.arg=new TypeError("iterator result is not an object"),e.delegate=null,g)}function B(t){var e={tryLoc:t[0]};1 in t&&(e.catchLoc=t[1]),2 in t&&(e.finallyLoc=t[2],e.afterLoc=t[3]),this.tryEntries.push(e)}function N(t){var e=t.completion||{};e.type="normal",delete e.arg,t.completion=e}function k(t){this.tryEntries=[{tryLoc:"root"}],t.forEach(B,this),this.reset(!0)}function T(e){if(e||""===e){var n=e[u];if(n)return n.call(e);if("function"==typeof e.next)return e;if(!isNaN(e.length)){var o=-1,c=function t(){for(;++o<e.length;)if(i.call(e,o))return t.value=e[o],t.done=!1,t;return t.value=r,t.done=!0,t};return c.next=c}}throw new TLine truncated
|
||||
//# sourceMappingURL=taskpane.js.map
|
||||
@@ -1 +0,0 @@
|
||||
/*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */
|
||||
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"taskpane.js","mappings":"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 truncated
|
||||