Update to edge-tts 4.0.0
This commit is contained in:
166
src/edge_tts/util.py
Normal file
166
src/edge_tts/util.py
Normal file
@@ -0,0 +1,166 @@
|
||||
"""
|
||||
Main package.
|
||||
"""
|
||||
|
||||
|
||||
import argparse
|
||||
import asyncio
|
||||
import sys
|
||||
|
||||
from edge_tts import Communicate, SubMaker, list_voices
|
||||
|
||||
|
||||
async def _list_voices():
|
||||
"""
|
||||
List available voices.
|
||||
"""
|
||||
for idx, voice in enumerate(await list_voices()):
|
||||
if idx != 0:
|
||||
print()
|
||||
|
||||
for key in voice.keys():
|
||||
if key in ["SuggestedCodec", "FriendlyName", "Status"]:
|
||||
continue
|
||||
# print ("%s: %s" % ("Name" if key == "ShortName" else key, voice[key]))
|
||||
print(f"{key}: {voice[key]}")
|
||||
|
||||
|
||||
async def _tts(args):
|
||||
tts = Communicate()
|
||||
subs = SubMaker(args.overlapping)
|
||||
if args.write_media:
|
||||
media_file = open(args.write_media, "wb") # pylint: disable=consider-using-with
|
||||
async for i in tts.run(
|
||||
args.text,
|
||||
args.enable_sentence_boundary,
|
||||
args.enable_word_boundary,
|
||||
args.codec,
|
||||
args.voice,
|
||||
args.pitch,
|
||||
args.rate,
|
||||
args.volume,
|
||||
customspeak=args.custom_ssml,
|
||||
):
|
||||
if i[2] is not None:
|
||||
if not args.write_media:
|
||||
sys.stdout.buffer.write(i[2])
|
||||
else:
|
||||
media_file.write(i[2])
|
||||
elif i[0] is not None and i[1] is not None:
|
||||
subs.create_sub(i[0], i[1])
|
||||
if args.write_media:
|
||||
media_file.close()
|
||||
if not args.write_subtitles:
|
||||
sys.stderr.write(subs.generate_subs())
|
||||
else:
|
||||
with open(args.write_subtitles, "w", encoding="utf-8") as file:
|
||||
file.write(subs.generate_subs())
|
||||
|
||||
|
||||
async def _main():
|
||||
parser = argparse.ArgumentParser(description="Microsoft Edge TTS")
|
||||
group = parser.add_mutually_exclusive_group(required=True)
|
||||
group.add_argument("-t", "--text", help="what TTS will say")
|
||||
group.add_argument("-f", "--file", help="same as --text but read from file")
|
||||
parser.add_argument(
|
||||
"-z",
|
||||
"--custom-ssml",
|
||||
help="treat text as ssml to send. For more info check https://bit.ly/3fIq13S",
|
||||
action="store_true",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-v",
|
||||
"--voice",
|
||||
help="voice for TTS. "
|
||||
"Default: Microsoft Server Speech Text to Speech Voice (en-US, AriaNeural)",
|
||||
default="Microsoft Server Speech Text to Speech Voice (en-US, AriaNeural)",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-c",
|
||||
"--codec",
|
||||
help="codec format. Default: audio-24khz-48kbitrate-mono-mp3. "
|
||||
"Another choice is webm-24khz-16bit-mono-opus. "
|
||||
"For more info check https://bit.ly/2T33h6S",
|
||||
default="audio-24khz-48kbitrate-mono-mp3",
|
||||
)
|
||||
group.add_argument(
|
||||
"-l",
|
||||
"--list-voices",
|
||||
help="lists available voices. "
|
||||
"Edge's list is incomplete so check https://bit.ly/2SFq1d3",
|
||||
action="store_true",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-p",
|
||||
"--pitch",
|
||||
help="set TTS pitch. Default +0Hz, For more info check https://bit.ly/3eAE5Nx",
|
||||
default="+0Hz",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-r",
|
||||
"--rate",
|
||||
help="set TTS rate. Default +0%%. For more info check https://bit.ly/3eAE5Nx",
|
||||
default="+0%",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-V",
|
||||
"--volume",
|
||||
help="set TTS volume. Default +0%%. For more info check https://bit.ly/3eAE5Nx",
|
||||
default="+0%",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-s",
|
||||
"--enable-sentence-boundary",
|
||||
help="enable sentence boundary",
|
||||
action="store_true",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-w",
|
||||
"--enable-word-boundary",
|
||||
help="enable word boundary",
|
||||
action="store_true",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-O",
|
||||
"--overlapping",
|
||||
help="overlapping subtitles in seconds",
|
||||
default=5,
|
||||
type=float,
|
||||
)
|
||||
parser.add_argument(
|
||||
"--write-media", help="instead of stdout, send media output to provided file"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--write-subtitles",
|
||||
help="instead of stderr, send subtitle output to provided file",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.list_voices:
|
||||
await _list_voices()
|
||||
sys.exit(0)
|
||||
|
||||
if args.text is not None or args.file is not None:
|
||||
if args.file is not None:
|
||||
# we need to use sys.stdin.read() because some devices
|
||||
# like Windows and Termux don't have a /dev/stdin.
|
||||
if args.file == "/dev/stdin":
|
||||
# logger.debug("stdin detected, reading natively from stdin")
|
||||
args.text = sys.stdin.read()
|
||||
else:
|
||||
# logger.debug("reading from %s" % args.file)
|
||||
with open(args.file, "r", encoding="utf-8") as file:
|
||||
args.text = file.read()
|
||||
|
||||
await _tts(args)
|
||||
|
||||
|
||||
def main():
|
||||
"""
|
||||
Main function.
|
||||
"""
|
||||
asyncio.run(_main())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user