diff --git a/system/TGWUI_Extension/AT TGWUI Remote Instructions.txt b/system/TGWUI_Extension/AT TGWUI Remote Instructions.txt
new file mode 100644
index 0000000..ef94ced
--- /dev/null
+++ b/system/TGWUI_Extension/AT TGWUI Remote Instructions.txt
@@ -0,0 +1,17 @@
+Text-generation-webui remote extension for AllTalk!
+
+This folder contains everything you need to set up a Text-generation-webui extension that can communicate with an AllTalk server remotely.
+
+To get started, follow these simple steps:
+
+1) In your Text-generation-webui's extensions folder, create a new folder and name it "alltalk_tts".
+2) Take all the files from this current folder and copy them into the newly created "alltalk_tts" folder.
+3) Start & Open Text-generation-webui and look for "alltalk_tts" in the list of extensions. Select alltalk_tts, save your settings and restart Text-generation-webui.
+4) Text-generation-webui will restart and load the AllTalk extension. You may see an error/warning as the extension will not yet have the IP address details of your remote AllTalk server.
+5) In the extension settings, enter the correct IP address and port of your AllTalk server. If your AllTalk server is running on a remote machine accessed through a secure tunnel, make sure to use "https" instead of "http".
+6) After entering the server details, click on the "Refresh settings & voices" button. If the settings are correct, the extension will download all the available settings from the AllTalk server.
+7) The first time you successfully generate speech using the extension, the settings will be automatically saved to a local configuration file.
+
+Please note that if the AllTalk server you're connected to doesn't support certain settings/features, those options will be greyed out and unavailable in the extension.
+
+Please use the "Refresh settings & voices" button to make sure the extension is in sync with your AllTalk server.
\ No newline at end of file
diff --git a/system/TGWUI_Extension/deepspeeddisabled.wav b/system/TGWUI_Extension/deepspeeddisabled.wav
new file mode 100644
index 0000000..e276b47
Binary files /dev/null and b/system/TGWUI_Extension/deepspeeddisabled.wav differ
diff --git a/system/TGWUI_Extension/deepspeedenabled.wav b/system/TGWUI_Extension/deepspeedenabled.wav
new file mode 100644
index 0000000..e711b0f
Binary files /dev/null and b/system/TGWUI_Extension/deepspeedenabled.wav differ
diff --git a/system/TGWUI_Extension/harvard_sentences.txt b/system/TGWUI_Extension/harvard_sentences.txt
new file mode 100644
index 0000000..1947d9c
--- /dev/null
+++ b/system/TGWUI_Extension/harvard_sentences.txt
@@ -0,0 +1,720 @@
+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.
\ No newline at end of file
diff --git a/system/TGWUI_Extension/languages.json b/system/TGWUI_Extension/languages.json
new file mode 100644
index 0000000..3b780e8
--- /dev/null
+++ b/system/TGWUI_Extension/languages.json
@@ -0,0 +1,18 @@
+{
+ "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"
+}
\ No newline at end of file
diff --git a/system/TGWUI_Extension/lowvramdisabled.wav b/system/TGWUI_Extension/lowvramdisabled.wav
new file mode 100644
index 0000000..ac6fef9
Binary files /dev/null and b/system/TGWUI_Extension/lowvramdisabled.wav differ
diff --git a/system/TGWUI_Extension/lowvramenabled.wav b/system/TGWUI_Extension/lowvramenabled.wav
new file mode 100644
index 0000000..e165bb5
Binary files /dev/null and b/system/TGWUI_Extension/lowvramenabled.wav differ
diff --git a/system/TGWUI_Extension/script.py b/system/TGWUI_Extension/script.py
new file mode 100644
index 0000000..b6ca8f4
--- /dev/null
+++ b/system/TGWUI_Extension/script.py
@@ -0,0 +1,1391 @@
+import re
+import sys
+import json
+import time
+import inspect
+import random
+import logging
+import requests
+import threading
+import gradio as gr
+from pathlib import Path
+from modules import chat, shared, ui_chat
+from modules.utils import gradio
+from requests.exceptions import RequestException, ConnectionError
+
+# Store the current disable level
+current_disable_level = logging.getLogger().manager.disable
+this_dir = Path(__file__).parent.resolve()
+
+class TGWUIModeManager:
+ def __init__(self):
+ self.debug_tgwui = False # General Debugging setting. Default is `False`
+ self.debug_func = False # Print function name as its used. Default is `False`
+ self.is_local = self._detect_mode()
+ self._setup_config()
+ self._setup_server_connection()
+
+ def _detect_mode(self):
+ """Detect if we're running as part of AllTalk installation"""
+ try:
+ current_dir = Path(__file__).parent
+ alltalk_root = current_dir.parent.parent
+
+ # Just check if we're in the right place, don't import
+ required_files = [
+ alltalk_root / "confignew.json",
+ alltalk_root / "script.py"
+ ]
+ required_folders = [
+ alltalk_root / "system",
+ alltalk_root / "models",
+ alltalk_root / "outputs",
+ alltalk_root / "voices"
+ ]
+
+ files_exist = all(f.exists() for f in required_files)
+ folders_exist = all(f.is_dir() for f in required_folders)
+
+ return files_exist and folders_exist
+
+ except (ImportError, FileNotFoundError) as e:
+ # Don't try to use mode_manager here since it doesn't exist yet
+ print(f"Error detecting mode: {str(e)}")
+ return False
+
+ def _setup_config(self):
+ """Load appropriate configuration based on mode"""
+ if self.is_local:
+ # We're in TGWUI mode, use default settings
+ self.branding = "AllTalk "
+ self.server = {
+ "protocol": "http://",
+ "address": "127.0.0.1:7851", # Default port
+ "timeout": 5
+ }
+ # Set complete default config structure
+ self.config = {
+ "api_def": {
+ "api_port_number": 7851,
+ "api_use_legacy_api": False
+ },
+ "tgwui": {
+ "tgwui_activate_tts": True,
+ "tgwui_autoplay_tts": True,
+ "tgwui_narrator_enabled": "false",
+ "tgwui_non_quoted_text_is": "narrator",
+ "tgwui_deepspeed_enabled": False,
+ "tgwui_language": "English",
+ "tgwui_lowvram_enabled": False,
+ "tgwui_pitch_set": 0,
+ "tgwui_temperature_set": 0.75,
+ "tgwui_repetitionpenalty_set": 10,
+ "tgwui_generationspeed_set": 1,
+ "tgwui_narrator_voice": "Please Refresh Settings",
+ "tgwui_show_text": True,
+ "tgwui_character_voice": "Please Refresh Settings",
+ "tgwui_rvc_char_voice": "Disabled",
+ "tgwui_rvc_char_pitch": 0,
+ "tgwui_rvc_narr_voice": "Disabled",
+ "tgwui_rvc_narr_pitch": 0
+ },
+ "remote_connection": { # Add this section for local mode too
+ "use_legacy_api": False,
+ "server_protocol": "http://",
+ "server_address": "127.0.0.1:7851",
+ "connection_timeout": 5
+ }
+ }
+ else:
+ config_path = Path(__file__).parent / "tgwui_remote_config.json"
+ try:
+ with open(config_path, "r") as f:
+ self.config = json.load(f)
+ except (FileNotFoundError, json.JSONDecodeError) as e:
+ print(f"Error loading remote config ({str(e)}), using defaults")
+ self.config = {
+ "branding": "AllTalk ",
+ "tgwui": {
+ "tgwui_activate_tts": True,
+ "tgwui_autoplay_tts": False,
+ "tgwui_show_text": True,
+ "tgwui_narrator_enabled": "false",
+ "tgwui_non_quoted_text_is": "narrator",
+ "tgwui_deepspeed_enabled": False,
+ "tgwui_language": "English",
+ "tgwui_lowvram_enabled": False,
+ "tgwui_pitch_set": 0,
+ "tgwui_temperature_set": 0.75,
+ "tgwui_repetitionpenalty_set": 10,
+ "tgwui_generationspeed_set": 1.0,
+ "tgwui_narrator_voice": "Please Refresh Settings",
+ "tgwui_character_voice": "Please Refresh Settings",
+ "tgwui_rvc_char_voice": "Disabled",
+ "tgwui_rvc_char_pitch": 0,
+ "tgwui_rvc_narr_voice": "Disabled",
+ "tgwui_rvc_narr_pitch": 0
+ },
+ "remote_connection": {
+ "server_protocol": "http://",
+ "server_address": "127.0.0.1:7851",
+ "connection_timeout": 5,
+ "use_legacy_api": False
+ }
+ }
+
+ self.branding = self.config['branding']
+ self.server = {
+ "protocol": self.config['remote_connection']['server_protocol'],
+ "address": self.config['remote_connection']['server_address'],
+ "timeout": self.config['remote_connection']['connection_timeout']
+ }
+
+ def _setup_server_connection(self):
+ """Initialize API connection settings"""
+ self.server_url = f"{self.server['protocol']}{self.server['address']}"
+
+ def get_api_url(self, endpoint):
+ """Get full API URL for a given endpoint"""
+ return f"{self.server_url}/api/{endpoint}"
+
+ def save_settings(self):
+ """Save current settings to appropriate location"""
+ if self.is_local:
+ # We're in TGWUI mode, we don't need to save to AllTalk's config
+ # The settings are maintained by TGWUI
+ pass
+ else:
+ # In remote mode, save to local config file
+ settings = {
+ "branding": self.branding,
+ "tgwui": self.config["tgwui"],
+ "remote_connection": {
+ "server_protocol": self.server["protocol"],
+ "server_address": self.server["address"],
+ "connection_timeout": self.server["timeout"],
+ "use_legacy_api": self.config['remote_connection']['use_legacy_api']
+ }
+ }
+ config_path = Path(__file__).parent / "tgwui_remote_config.json"
+ with open(config_path, "w") as f:
+ json.dump(settings, f, indent=4)
+
+# Initialize mode manager at startup
+mode_manager = TGWUIModeManager()
+
+##########################
+# Central print function #
+##########################
+def print_func(message, message_type="standard", component="TTS", debug_type=None):
+ """Centralized print function for AllTalk messages
+
+ Args:
+ message (str): The message to print
+ message_type (str): Type of message ("standard", "warning", "error", "debug")
+ component (str): Component identifier ("TTS", "ENG", "Server", etc.)
+ debug_type (str, optional): Can be supplied on the call to specify things like:
+ - The function that is sending the debug request.
+ - The operation taking place
+ """
+ prefix = f"[{mode_manager.branding}{component}] "
+
+ if message_type == "warning":
+ print(f"{prefix}\033[91mWarning\033[0m {message}")
+ elif message_type == "error":
+ print(f"{prefix}\033[91mError\033[0m {message}")
+ elif message_type == "debug":
+ if debug_type is None:
+ debug_type = ""
+ color = "\033[92m" if "Function entry" in message else "\033[93m"
+ print(f"{prefix}\033[94mDebug\033[0m {color}{debug_type}\033[0m {message}")
+ else: # standard message
+ print(f"{prefix}{message}")
+
+def debug_func_entry():
+ """Print debug message for function entry if debug_func is enabled/true"""
+ if mode_manager.debug_func:
+ print_func("Function entry", "debug", debug_type=inspect.currentframe().f_back.f_code.co_name)
+
+# Load languages
+with open(Path(__file__).parent / "languages.json", encoding="utf8") as f:
+ languages = json.load(f)
+
+# Setup other globals
+process_lock = threading.Lock()
+models_available = None
+alltalk_settings = None
+current_model_loaded = None
+tts_model_loaded = None
+
+def get_alltalk_settings():
+ if mode_manager.debug_func:
+ print_func("Function entry", "debug", debug_type=inspect.currentframe().f_code.co_name)
+ global current_model_loaded, models_available
+
+ def log_error(message, status_code=None):
+ """Helper function for consistent error logging"""
+ if status_code:
+ print_func(f"{message} Status code:\n{status_code}", message_type="warning")
+ else:
+ print_func(f"{message}", message_type="warning")
+
+ try:
+ # Make all API requests
+ api_calls = {
+ "voices": requests.get(
+ mode_manager.get_api_url("voices"),
+ timeout=mode_manager.server["timeout"]
+ ),
+ "rvc": requests.get(
+ mode_manager.get_api_url("rvcvoices"),
+ timeout=mode_manager.server["timeout"]
+ ),
+ "settings": requests.get(
+ mode_manager.get_api_url("currentsettings"),
+ timeout=mode_manager.server["timeout"]
+ )
+ }
+
+ # Check if all responses are successful
+ if all(response.status_code == 200 for response in api_calls.values()):
+ try:
+ voices_data = api_calls["voices"].json()
+ rvcvoices_data = api_calls["rvc"].json()
+ settings_data = api_calls["settings"].json()
+
+ # Update global variables
+ models_available = [model["name"] for model in settings_data["models_available"]]
+ current_model_loaded = settings_data["current_model_loaded"]
+
+ # Update our local config with received values
+ if mode_manager.is_local:
+ mode_manager.config["tgwui"].update({
+ "tgwui_character_voice": voices_data["voices"][0] if voices_data["voices"] else "Please Refresh Settings",
+ "tgwui_narrator_voice": voices_data["voices"][0] if voices_data["voices"] else "Please Refresh Settings",
+ "tgwui_rvc_char_voice": rvcvoices_data["rvcvoices"][0] if rvcvoices_data["rvcvoices"] else "Disabled",
+ "tgwui_rvc_narr_voice": rvcvoices_data["rvcvoices"][0] if rvcvoices_data["rvcvoices"] else "Disabled",
+ })
+
+ return AllTalkServerSettings.from_api_response(
+ voices_data,
+ rvcvoices_data,
+ settings_data
+ )
+ except json.JSONDecodeError as e:
+ log_error(f"Failed to decode JSON response: {e}")
+ return AllTalkServerSettings()
+ else:
+ # Log specific failures
+ log_error(f"Failed to retrieve {mode_manager.branding}settings from API.")
+ for name, response in api_calls.items():
+ if response.status_code != 200:
+ log_error(f"Failed to retrieve {name} from API", response.status_code)
+ return AllTalkServerSettings()
+
+ except (RequestException, ConnectionError) as e:
+ log_error(f"Unable to connect to the {mode_manager.branding}server", str(e))
+ return AllTalkServerSettings()
+
+class AllTalkServerSettings:
+ def __init__(self):
+ # Voice and model settings
+ self.voices = ["Please Refresh Settings"]
+ self.rvcvoices = ["Please Refresh Settings"]
+ self.models_available = ["Please Refresh Settings"]
+ self.current_model_loaded = "Please Refresh Settings"
+ self.manufacturer_name = ""
+
+ # Engine capabilities
+ self.deepspeed_capable = False
+ self.deepspeed_available = False
+ self.deepspeed_enabled = False
+ self.languages_capable = False
+ self.multivoice_capable = False
+ self.multimodel_capable = False
+ self.streaming_capable = False
+ self.ttsengines_installed = False
+
+ # Generation settings
+ self.generationspeed_capable = False
+ self.generationspeed_set = 1.0
+ self.lowvram_capable = False
+ self.lowvram_enabled = False
+ self.pitch_capable = False
+ self.pitch_set = 0
+ self.repetitionpenalty_capable = False
+ self.repetitionpenalty_set = 10.0
+ self.temperature_capable = False
+ self.temperature_set = 0.75
+
+ @classmethod
+ def from_api_response(cls, voices_data, rvcvoices_data, settings_data):
+ """Create settings instance from API response data"""
+ debug_func_entry()
+ if mode_manager.debug_func:
+ print_func("Function entry", "debug", debug_type=inspect.currentframe().f_code.co_name)
+ settings = cls()
+
+ # Update voice and model information
+ settings.voices = sorted(voices_data["voices"])
+ settings.rvcvoices = rvcvoices_data["rvcvoices"]
+ settings.models_available = [model["name"] for model in settings_data["models_available"]]
+ settings.current_model_loaded = settings_data["current_model_loaded"]
+ settings.manufacturer_name = settings_data.get("manufacturer_name", "")
+
+ # Update capabilities and settings
+ settings_mapping = {
+ # Capabilities
+ "deepspeed_capable": ("deepspeed_capable", False),
+ "deepspeed_available": ("deepspeed_available", False),
+ "deepspeed_enabled": ("deepspeed_enabled", False),
+ "languages_capable": ("languages_capable", False),
+ "multivoice_capable": ("multivoice_capable", False),
+ "multimodel_capable": ("multimodel_capable", False),
+ "streaming_capable": ("streaming_capable", False),
+ "ttsengines_installed": ("ttsengines_installed", False),
+
+ # Generation settings
+ "generationspeed_capable": ("generationspeed_capable", False),
+ "generationspeed_set": ("generationspeed_set", 1.0),
+ "lowvram_capable": ("lowvram_capable", False),
+ "lowvram_enabled": ("lowvram_enabled", False),
+ "pitch_capable": ("pitch_capable", False),
+ "pitch_set": ("pitch_enabled", 0),
+ "repetitionpenalty_capable": ("repetitionpenalty_capable", False),
+ "repetitionpenalty_set": ("repetitionpenalty_set", 10.0),
+ "temperature_capable": ("temperature_capable", False),
+ "temperature_set": ("temperature_set", 0.75),
+ }
+
+ # Update all settings from the mapping
+ for attr, (key, default) in settings_mapping.items():
+ setattr(settings, attr, settings_data.get(key, default))
+
+ return settings
+
+
+# Print Spashscreen to console if running as Remote Extension
+if not mode_manager.is_local:
+ print_func("\033[94m _ _ _ \033[1;35m_____ _ _ \033[0m _____ _____ ____ ")# pylint: disable=line-too-long anomalous-backslash-in-string
+ print_func("\033[94m / \ | | |\033[1;35m_ _|_ _| | | __ \033[0m |_ _|_ _/ ___| ")# pylint: disable=line-too-long anomalous-backslash-in-string
+ print_func("\033[94m / _ \ | | |\033[1;35m | |/ _` | | |/ / \033[0m | | | | \___ \ ")# pylint: disable=line-too-long anomalous-backslash-in-string
+ print_func("\033[94m / ___ \| | |\033[1;35m | | (_| | | < \033[0m | | | | ___) |")# pylint: disable=line-too-long anomalous-backslash-in-string
+ print_func("\033[94m /_/ \_\_|_|\033[1;35m |_|\__,_|_|_|\_\ \033[0m |_| |_| |____/ ")# pylint: disable=line-too-long anomalous-backslash-in-string
+ print_func("")
+ print_func(f"\033[92m{mode_manager.branding}startup Mode : \033[93mText-Gen-webui Remote\033[0m")
+ print_func("")
+
+def stop_generate_tts():
+ """Sends request to stop current TTS generation"""
+ debug_func_entry()
+ api_url = mode_manager.get_api_url("stop-generation")
+
+ if mode_manager.debug_tgwui:
+ print_func("Attempting to stop TTS generation", message_type="debug", debug_type="stop_generate_tts")
+
+ try:
+ response = requests.put(api_url, timeout=mode_manager.server["timeout"])
+ if response.status_code == 200:
+ return response.json()["message"]
+ else:
+ print_func(f"Failed to stop generation. Status code:\n{response.status_code}", message_type="warning")
+ return {"message": "Failed to stop generation"}
+ except (RequestException, ConnectionError) as e:
+ print_func(f"Unable to connect to the {mode_manager.branding}server. Status code:\n{str(e)}", message_type="warning")
+ return {"message": "Failed to stop generation"}
+
+def send_reload_request(value_sent):
+ """Requests AllTalk server to load a different TTS model"""
+ debug_func_entry()
+ global tts_model_loaded
+ if not process_lock.acquire(blocking=False):
+ return {"status": "error", "message": "Server is currently busy. Try again in a few seconds."}
+ try:
+ tts_model_loaded = False
+ url = mode_manager.get_api_url("reload")
+ payload = {"tts_method": value_sent}
+
+ if mode_manager.debug_tgwui:
+ print_func(f"Requesting model reload to: {value_sent}", message_type="debug", debug_type="send_reload_request")
+
+ response = requests.post(url, params=payload)
+ response.raise_for_status()
+ tts_model_loaded = True
+ except requests.exceptions.RequestException as e:
+ print_func(f"Error during request to webserver process: Status code:\n{e}", message_type="warning")
+ tts_model_loaded = True
+ return {"status": "error", "message": str(e)}
+ finally:
+ process_lock.release()
+
+def send_lowvram_request(value_sent):
+ """Toggles low VRAM mode in AllTalk server"""
+ debug_func_entry()
+ global tts_model_loaded
+ if not process_lock.acquire(blocking=False):
+ return {"status": "error", "message": "Server is currently busy. Try again in a few seconds."}
+ try:
+ tts_model_loaded = False
+ audio_path = this_dir / ("lowvramenabled.wav" if value_sent else "lowvramdisabled.wav")
+
+ if mode_manager.debug_tgwui:
+ print_func(f"Setting low VRAM mode to: {value_sent}", message_type="debug", debug_type="send_lowvram_request")
+
+ url = mode_manager.get_api_url(f"lowvramsetting?new_low_vram_value={value_sent}")
+ response = requests.post(url, headers={"Content-Type": "application/json"})
+ response.raise_for_status()
+
+ json_response = response.json()
+ if json_response.get("status") == "lowvram-success":
+ tts_model_loaded = True
+
+ return f''
+ except requests.exceptions.RequestException as e:
+ print_func(f"Error during request to webserver process: Status code:\n{e}", message_type="warning")
+ return {"status": "error", "message": str(e)}
+ finally:
+ process_lock.release()
+
+def send_deepspeed_request(value_sent):
+ """Toggles DeepSpeed acceleration in AllTalk server"""
+ debug_func_entry()
+ global tts_model_loaded
+ if not process_lock.acquire(blocking=False):
+ return {"status": "error", "message": "Server is currently busy. Try again in a few seconds."}
+ try:
+ tts_model_loaded = False
+ audio_path = this_dir / ("deepspeedenabled.wav" if value_sent else "deepspeeddisabled.wav")
+
+ if mode_manager.debug_tgwui:
+ print_func(f"Setting DeepSpeed to: {value_sent}", message_type="debug", debug_type="send_deepspeed_request")
+
+ url = mode_manager.get_api_url(f"deepspeed?new_deepspeed_value={value_sent}")
+ response = requests.post(url, headers={"Content-Type": "application/json"})
+ response.raise_for_status()
+
+ json_response = response.json()
+ if json_response.get("status") == "deepspeed-success":
+ tts_model_loaded = True
+
+ process_lock.release()
+ return f''
+ except requests.exceptions.RequestException as e:
+ print_func(f"Error during request to webserver process: Status code:\n{e}", message_type="warning")
+ return {"status": "error", "message": str(e)}
+ finally:
+ process_lock.release()
+
+def send_and_generate(gen_text, gen_character_voice, gen_rvccharacter_voice, gen_rvccharacter_pitch, gen_narrator_voice, gen_rvcnarrator_voice,
+ gen_rvcnarrator_pitch, gen_narrator_activated, gen_textnotinisde, gen_repetition, gen_language, gen_filter, gen_speed,
+ gen_pitch, gen_autoplay, gen_autoplay_vol, gen_file_name, gen_temperature, gen_filetimestamp,
+ gen_stream, gen_stopcurrentgen):
+ """Sends text to AllTalk server for TTS generation"""
+ debug_func_entry()
+ api_url = mode_manager.get_api_url("tts-generate")
+
+ if mode_manager.debug_tgwui:
+ print_func("Starting TTS generation request", message_type="debug", debug_type="send_and_generate")
+
+ if gen_stopcurrentgen:
+ stop_generate_tts()
+
+ mode_manager.save_settings()
+
+ if gen_stream == "true":
+ api_url = mode_manager.get_api_url("tts-generate-streaming")
+ encoded_text = requests.utils.quote(gen_text)
+ streaming_url = f"{api_url}?text={encoded_text}&voice={gen_character_voice}&language={gen_language}&output_file={gen_file_name}"
+ return streaming_url, str("TTS Streaming Audio Generated")
+
+ data = {
+ "text_input": gen_text,
+ "text_filtering": gen_filter,
+ "character_voice_gen": gen_character_voice,
+ "rvccharacter_voice_gen": gen_rvccharacter_voice,
+ "rvccharacter_pitch": gen_rvccharacter_pitch,
+ "narrator_enabled": str(gen_narrator_activated).lower(),
+ "narrator_voice_gen": gen_narrator_voice,
+ "rvcnarrator_voice_gen": gen_rvcnarrator_voice,
+ "rvcnarrator_pitch": gen_rvcnarrator_pitch,
+ "text_not_inside": gen_textnotinisde,
+ "language": gen_language,
+ "output_file_name": str(gen_file_name),
+ "output_file_timestamp": str(gen_filetimestamp).lower(),
+ "autoplay": str(gen_autoplay).lower(),
+ "autoplay_volume": str(gen_autoplay_vol),
+ "speed": str(gen_speed),
+ "pitch": str(gen_pitch),
+ "temperature": str(gen_temperature),
+ "repetition_penalty": str(gen_repetition),
+ }
+
+ if mode_manager.debug_tgwui:
+ print_func("Generation request parameters:", message_type="debug", debug_type="send_and_generate")
+ for key, value in data.items():
+ print_func(f"{key}: {value}", message_type="debug", debug_type="send_and_generate")
+
+ try:
+ response = requests.post(api_url, data=data)
+ response.raise_for_status()
+ result = response.json()
+
+ if gen_autoplay == "true":
+ return None, str("TTS Audio Generated (Played remotely)")
+
+ if mode_manager.config["remote_connection"]["use_legacy_api"]:
+ return result['output_file_url'], str("TTS Audio Generated")
+ else:
+ output_file_url = f"{mode_manager.server_url}{result['output_file_url']}"
+ return output_file_url, str("TTS Audio Generated")
+ except (RequestException, ConnectionError) as e:
+ print_func(f"Error occurred during the API request: Status code:\n{str(e)}", message_type="warning")
+ return None, str("Error occurred during the API request")
+
+def output_modifier(string, state):
+ """Modifies TGWUI output to include TTS audio"""
+ debug_func_entry()
+ if not mode_manager.config["tgwui"]["tgwui_activate_tts"]:
+ return string
+
+ if mode_manager.debug_tgwui:
+ print_func("Processing text for TTS generation", message_type="debug", debug_type="output_modifier")
+
+ # Strip out Images
+ img_info = ""
+ cleaned_text, img_info = tgwui_extract_and_remove_images(string)
+ if cleaned_text is None:
+ return
+
+ # Get current settings
+ language_code = languages.get(mode_manager.config["tgwui"]["tgwui_language"])
+ character_voice = mode_manager.config["tgwui"]["tgwui_character_voice"]
+ rvc_character_voice = mode_manager.config["tgwui"]["tgwui_rvc_char_voice"]
+ rvc_character_pitch = mode_manager.config["tgwui"]["tgwui_rvc_char_pitch"]
+ narrator_voice = mode_manager.config["tgwui"]["tgwui_narrator_voice"]
+ rvc_narrator_voice = mode_manager.config["tgwui"]["tgwui_rvc_narr_voice"]
+ rvc_narrator_pitch = mode_manager.config["tgwui"]["tgwui_rvc_narr_pitch"]
+ narrator_enabled = mode_manager.config["tgwui"]["tgwui_narrator_enabled"]
+ text_not_inside = mode_manager.config["tgwui"]["tgwui_non_quoted_text_is"]
+ repetition_policy = mode_manager.config["tgwui"]["tgwui_repetitionpenalty_set"]
+ speed = mode_manager.config["tgwui"]["tgwui_generationspeed_set"]
+ pitch = mode_manager.config["tgwui"]["tgwui_pitch_set"]
+ temperature = mode_manager.config["tgwui"]["tgwui_temperature_set"]
+
+ if mode_manager.debug_tgwui:
+ print_func(f"Using character voice: {character_voice}, narrator voice: {narrator_voice}",
+ message_type="debug", debug_type="output_modifier")
+ print_func(f"Text length: {len(cleaned_text)} characters",
+ message_type="debug", debug_type="output_modifier")
+
+ # Lock and process TTS request
+ if process_lock.acquire(blocking=False):
+ try:
+ output_file = state["character_menu"] if "character_menu" in state else str("TTSOUT_")
+ # Ensure the file name matches the allowed pattern of AllTalk
+ output_file = re.sub(r"[^a-zA-Z0-9_]", "", output_file)
+
+ generate_response, status_message = send_and_generate(
+ cleaned_text, character_voice, rvc_character_voice, rvc_character_pitch, narrator_voice,
+ rvc_narrator_voice, rvc_narrator_pitch, narrator_enabled, text_not_inside, repetition_policy,
+ language_code, "html", speed, pitch, False, 0.8, output_file,
+ temperature, True, False, False
+ )
+
+ if status_message == "TTS Audio Generated":
+ autoplay = "autoplay" if mode_manager.config["tgwui"]["tgwui_autoplay_tts"] else ""
+ string = f''
+
+ if mode_manager.config["tgwui"]["tgwui_show_text"]:
+ string += tgwui_reinsert_images(cleaned_text, img_info)
+
+ shared.processing_message = "*Is typing...*"
+ return string
+ else:
+ print_func(f"Audio generation failed. Status code:\n{status_message}", message_type="warning")
+ finally:
+ process_lock.release()
+ else:
+ print_func("Audio generation is already in progress. Please wait.", message_type="warning")
+ return
+
+@debounce
+def voice_preview(string):
+ """Generates a preview of the selected voice settings"""
+ # debug_func_entry()
+ print("in voice preview function")
+ if not mode_manager.config["tgwui"]["tgwui_activate_tts"]:
+ return string
+
+ if mode_manager.debug_tgwui:
+ print_func("Generating voice preview", message_type="debug", debug_type="voice_preview")
+
+ language_code = languages.get(mode_manager.config["tgwui"]["tgwui_language"])
+ if not string:
+ string = random_sentence()
+
+ if mode_manager.debug_tgwui:
+ print_func(f"Preview text: {string}", message_type="debug", debug_type="voice_preview")
+
+ generate_response, status_message = send_and_generate(
+ string,
+ mode_manager.config["tgwui"]["tgwui_character_voice"],
+ mode_manager.config["tgwui"]["tgwui_rvc_char_voice"],
+ mode_manager.config["tgwui"]["tgwui_rvc_char_pitch"],
+ mode_manager.config["tgwui"]["tgwui_narrator_voice"],
+ mode_manager.config["tgwui"]["tgwui_rvc_narr_voice"],
+ mode_manager.config["tgwui"]["tgwui_rvc_narr_pitch"],
+ False, "character",
+ mode_manager.config["tgwui"]["tgwui_repetitionpenalty_set"],
+ language_code, "standard",
+ mode_manager.config["tgwui"]["tgwui_generationspeed_set"],
+ mode_manager.config["tgwui"]["tgwui_pitch_set"],
+ False, 0.8, "previewvoice",
+ mode_manager.config["tgwui"]["tgwui_temperature_set"],
+ False, False, False
+ )
+
+ if status_message == "TTS Audio Generated":
+ autoplay = "autoplay" if mode_manager.config["tgwui"]["tgwui_autoplay_tts"] else ""
+ return f''
+ else:
+ return f"[{mode_manager.branding}Server] Audio generation failed. Status code:\n{status_message}"
+
+img_pattern = r']*src\s*=\s*["\'][^"\'>]+["\'][^>]*>'
+
+def tgwui_extract_and_remove_images(text):
+ """Extracts and removes image tags from text for clean TTS processing"""
+ debug_func_entry()
+ img_matches = re.findall(img_pattern, text)
+ img_info = "\n".join(img_matches)
+ cleaned_text = re.sub(img_pattern, '', text)
+
+ if mode_manager.debug_tgwui:
+ print_func(f"Found {len(img_matches)} images in text", message_type="debug", debug_type="extract_images")
+
+ return cleaned_text, img_info
+
+def tgwui_reinsert_images(text, img_info):
+ """Reinserts the previously extracted image data back into the text"""
+ debug_func_entry()
+ if img_info: # Check if there are images to reinsert
+ text += f"\n\n{img_info}"
+ return text
+
+################################################################
+# TGWUI # Used to generate a preview voice sample within TGWUI #
+################################################################
+def random_sentence():
+ """Returns a random sentence from Harvard sentences file for voice preview"""
+ debug_func_entry()
+ with open(this_dir / "harvard_sentences.txt") as f:
+ return random.choice(list(f)).rstrip()
+
+###################################################################
+# TGWUI # Used to inform TGWUI that TTS is disabled/not activated #
+###################################################################
+def state_modifier(state):
+ """Modifies TGWUI state to disable streaming when TTS is active"""
+ debug_func_entry()
+ if not mode_manager.config["tgwui"]["tgwui_activate_tts"]:
+ return state
+
+ if mode_manager.debug_tgwui:
+ print_func("Disabling streaming for TTS", message_type="debug", debug_type="state_modifier")
+
+ state["stream"] = False
+ return state
+
+###################################################################
+# TGWUI # Sends message to TGWUI interface during TTS generation #
+###################################################################
+def input_modifier(string, state):
+ """Updates TGWUI interface message during TTS processing"""
+ debug_func_entry()
+ if not mode_manager.config["tgwui"]["tgwui_activate_tts"]:
+ return string
+
+ if mode_manager.debug_tgwui:
+ print_func("Setting processing message for TTS", message_type="debug", debug_type="input_modifier")
+
+ shared.processing_message = "*Is recording a voice message...*"
+ return string
+
+########################################################################
+# TGWUI # Used to delete historic TTS audios from TGWUI chat interface #
+########################################################################
+def remove_tts_from_history(history):
+ '''Removes audio from the chat with TGWUI's chat interface'''
+ debug_func_entry()
+ for i, entry in enumerate(history["internal"]):
+ history["visible"][i] = [history["visible"][i][0], entry[1]]
+ return history
+
+def toggle_text_in_history(history):
+ '''Hides text from the chat with TGWUI's chat interface'''
+ debug_func_entry()
+ for i, entry in enumerate(history["visible"]):
+ visible_reply = entry[1]
+ if visible_reply.startswith("\n\n{reply}",
+ ]
+ else:
+ history["visible"][i] = [
+ history["visible"][i][0],
+ f"{visible_reply.split('')[0]}",
+ ]
+ return history
+
+def history_modifier(history):
+ '''Controls/Enables autoplay of TTS in TGWUI interface'''
+ debug_func_entry()
+ # Remove autoplay from the last reply
+ if len(history["internal"]) > 0:
+ history["visible"][-1] = [
+ history["visible"][-1][0],
+ history["visible"][-1][1].replace("controls autoplay>", "controls>"),
+ ]
+ return history
+
+def tgwui_update_alltalk_protocol(value_sent):
+ """Updates the server protocol setting"""
+ debug_func_entry()
+ if mode_manager.debug_tgwui:
+ print_func(f"Updating server protocol to: {value_sent}",
+ message_type="debug", debug_type="update_protocol")
+ mode_manager.server["protocol"] = value_sent
+
+def tgwui_update_alltalk_ip_port(value_sent):
+ """Updates the server address settings"""
+ debug_func_entry()
+ if mode_manager.debug_tgwui:
+ print_func(f"Updating server address to: {value_sent}",
+ message_type="debug", debug_type="update_ip_port")
+ mode_manager.server["address"] = value_sent
+
+def tgwui_handle_ttsmodel_dropdown_change(model_name):
+ """Handles model changes from Gradio dropdown, with debounce protection"""
+ debug_func_entry()
+ if not getattr(tgwui_handle_ttsmodel_dropdown_change, "skip_reload", False):
+ if mode_manager.debug_tgwui:
+ print_func(f"Switching model to: {model_name}", message_type="debug", debug_type="model_change")
+ send_reload_request(model_name)
+ else:
+ if mode_manager.debug_tgwui:
+ print_func("Skipping model reload (debounced)", message_type="debug", debug_type="model_change")
+ tgwui_handle_ttsmodel_dropdown_change.skip_reload = False
+
+def tgwui_update_dropdowns():
+ """Updates all Gradio dropdowns with current server settings"""
+ debug_func_entry()
+ global at_settings
+
+ if mode_manager.debug_tgwui:
+ print_func("Refreshing server settings", message_type="debug", debug_type="update_dropdowns")
+
+ at_settings = get_alltalk_settings()
+
+ if mode_manager.debug_tgwui:
+ print_func(f"Retrieved {len(at_settings.voices)} voices", message_type="debug", debug_type="update_dropdowns")
+ print_func(f"Retrieved {len(at_settings.rvcvoices)} RVC voices", message_type="debug", debug_type="update_dropdowns")
+ print_func(f"Current model: {at_settings.current_model_loaded}", message_type="debug", debug_type="update_dropdowns")
+
+ current_voices = at_settings.voices
+ rvccurrent_voices = at_settings.rvcvoices
+ rvccurrent_character_voice = mode_manager.config["tgwui"]["tgwui_rvc_char_voice"]
+ rvccurrent_character_pitch = mode_manager.config["tgwui"]["tgwui_rvc_char_pitch"]
+ rvccurrent_narrator_voice = mode_manager.config["tgwui"]["tgwui_rvc_char_voice"]
+ rvccurrent_narrator_pitch = mode_manager.config["tgwui"]["tgwui_rvc_char_pitch"]
+ current_models_available = sorted(at_settings.models_available)
+ current_model_loaded = at_settings.current_model_loaded
+ current_character_voice = mode_manager.config["tgwui"]["tgwui_character_voice"]
+ current_narrator_voice = mode_manager.config["tgwui"]["tgwui_narrator_voice"]
+
+ # Capability checks
+ current_lowvram_capable = at_settings.lowvram_capable
+ current_lowvram_enabled = at_settings.lowvram_enabled
+ current_temperature_capable = at_settings.temperature_capable
+ current_repetitionpenalty_capable = at_settings.repetitionpenalty_capable
+ current_generationspeed_capable = at_settings.generationspeed_capable
+ current_pitch_capable = at_settings.pitch_capable
+ current_deepspeed_capable = at_settings.deepspeed_capable
+ current_deepspeed_enabled = at_settings.deepspeed_enabled
+ current_non_quoted_text_is = mode_manager.config["tgwui"]["tgwui_non_quoted_text_is"]
+ current_languages_capable = at_settings.languages_capable
+
+ # Set appropriate labels based on capabilities
+ language_label = "Languages" if at_settings.languages_capable else "Model not multi language"
+
+ # Update voice selections if needed
+ if current_character_voice not in current_voices:
+ if mode_manager.debug_tgwui:
+ print_func(f"Character voice {current_character_voice} not found, resetting",
+ message_type="debug", debug_type="update_dropdowns")
+ current_character_voice = current_voices[0] if current_voices else ""
+ mode_manager.config["tgwui"]["tgwui_character_voice"] = current_character_voice
+
+ if current_narrator_voice not in current_voices:
+ if mode_manager.debug_tgwui:
+ print_func(f"Narrator voice {current_narrator_voice} not found, resetting",
+ message_type="debug", debug_type="update_dropdowns")
+ current_narrator_voice = current_voices[0] if current_voices else ""
+ mode_manager.config["tgwui"]["tgwui_narrator_voice"] = current_narrator_voice
+
+ # Update RVC voice selections if needed
+ if rvccurrent_character_voice not in rvccurrent_voices:
+ if mode_manager.debug_tgwui:
+ print_func(f"RVC character voice {rvccurrent_character_voice} not found, resetting",
+ message_type="debug", debug_type="update_dropdowns")
+ rvccurrent_character_voice = rvccurrent_voices[0] if rvccurrent_voices else ""
+ mode_manager.config["tgwui"]["tgwui_rvc_char_voice"] = rvccurrent_character_voice
+
+ if rvccurrent_narrator_voice not in rvccurrent_voices:
+ if mode_manager.debug_tgwui:
+ print_func(f"RVC narrator voice {rvccurrent_narrator_voice} not found, resetting",
+ message_type="debug", debug_type="update_dropdowns")
+ rvccurrent_narrator_voice = rvccurrent_voices[0] if rvccurrent_voices else ""
+ mode_manager.config["tgwui"]["tgwui_rvc_char_voice"] = rvccurrent_narrator_voice
+
+ rvccurrent_character_pitch = rvccurrent_character_pitch if rvccurrent_character_pitch else 0
+ rvccurrent_narrator_pitch = rvccurrent_narrator_pitch if rvccurrent_narrator_pitch else 0
+
+ # Prevent model reload during update
+ tgwui_handle_ttsmodel_dropdown_change.skip_reload = True
+
+ # Return updated Gradio components
+ return_values = [
+ gr.Checkbox(interactive=current_lowvram_capable, value=current_lowvram_enabled),
+ gr.Checkbox(interactive=current_deepspeed_capable, value=current_deepspeed_enabled),
+ gr.Dropdown(choices=current_voices, value=current_character_voice),
+ gr.Dropdown(choices=rvccurrent_voices, value=rvccurrent_character_voice, interactive=True),
+ gr.Slider(value=rvccurrent_character_pitch),
+ gr.Dropdown(choices=current_voices, value=current_narrator_voice),
+ gr.Dropdown(choices=rvccurrent_voices, value=rvccurrent_narrator_voice, interactive=True),
+ gr.Slider(value=rvccurrent_narrator_pitch),
+ gr.Dropdown(choices=current_models_available, value=current_model_loaded),
+ gr.Dropdown(interactive=current_temperature_capable),
+ gr.Dropdown(interactive=current_repetitionpenalty_capable),
+ gr.Dropdown(interactive=current_languages_capable, label=language_label),
+ gr.Dropdown(interactive=current_generationspeed_capable),
+ gr.Dropdown(interactive=current_pitch_capable),
+ gr.Dropdown(value=current_non_quoted_text_is),
+ ]
+
+ def reset_skip_reload():
+ tgwui_handle_ttsmodel_dropdown_change.skip_reload = False
+
+ threading.Timer(0.5, reset_skip_reload).start()
+
+ return return_values
+
+def ui():
+ """Creates the TGWUI Gradio interface"""
+ global alltalk_settings
+
+ if mode_manager.debug_tgwui:
+ print_func("Initializing TGWUI interface", message_type="debug", debug_type="ui")
+
+ alltalk_settings = get_alltalk_settings()
+
+ with gr.Accordion(mode_manager.branding + " TTS (Text-gen-webui Remote)"):
+ tgwui_available_voices_gr = alltalk_settings.voices
+ tgwui_rvc_available_voices_gr = alltalk_settings.rvcvoices
+
+ # Activate alltalk_tts, Enable autoplay, Show text
+ with gr.Row():
+ tgwui_activate_tts_gr = gr.Checkbox(
+ value=mode_manager.config["tgwui"]["tgwui_activate_tts"],
+ label="Enable TGWUI TTS"
+ )
+ tgwui_autoplay_gr = gr.Checkbox(
+ value=mode_manager.config["tgwui"]["tgwui_autoplay_tts"],
+ label="Autoplay TTS Generated"
+ )
+ tgwui_show_text_gr = gr.Checkbox(
+ value=mode_manager.config["tgwui"]["tgwui_show_text"],
+ label="Show Text in chat"
+ )
+
+ # Low vram enable, Deepspeed enable, Link
+ with gr.Row():
+ tgwui_lowvram_enabled_gr = gr.Checkbox(
+ value=alltalk_settings.lowvram_enabled if alltalk_settings.lowvram_capable else False,
+ label="Enable Low VRAM Mode",
+ interactive=alltalk_settings.lowvram_capable
+ )
+ tgwui_lowvram_enabled_play_gr = gr.HTML(visible=False)
+
+ tgwui_deepspeed_enabled_gr = gr.Checkbox(
+ value=mode_manager.config["tgwui"]["tgwui_deepspeed_enabled"],
+ label="Enable DeepSpeed",
+ interactive=alltalk_settings.deepspeed_capable
+ )
+ tgwui_deepspeed_enabled_play_gr = gr.HTML(visible=False)
+
+ tgwui_empty_space_gr = gr.HTML(
+ f"