Skip to content

As you know, Microsoft Edge browser has a powerful Read Aloud feature. It supports dozens of languages, each with different roles to choose from for pronunciation, and the effect is quite excellent.

Based on this, a developer created a Python package called edge-tts. This package allows you to use Microsoft's TTS service in your programs to dub text or subtitles. For example, the video translation software pyVideoTrans integrates edge-tts, allowing users to select it directly as a dubbing channel.

However, unfortunately, there is a serious phenomenon of domestic users abusing Microsoft TTS, and some people even use it for commercial dubbing sales. This has led Microsoft to restrict access from within China. If used too frequently, a 403 error may occur. Only switching IPs or connecting to a stable foreign VPN will allow continued use.

So, can we use a foreign server to build a simple relay service for ourselves? This can not only improve stability, but also make the interface compatible with OpenAI TTS, so that it can be directly used in the OpenAI SDK.

The answer is yes. I recently took the time to create a Docker image that can be easily pulled and started on a server.

After starting, the service interface is fully compatible with OpenAI. Just change the API address to http://deployed_server_ip:7899/v1 to seamlessly replace OpenAI TTS. In addition, it can be used directly in video translation software.

The following will detail how to deploy and use it:

Step 1: Purchase and activate a US server

Step 2: Allow port 7899 in the firewall

Step 3: Connect to the terminal and log in to the server

Step 4: Install Docker

Step 5: Pull the edge-tts-api image and start the API service

If you already have a server with Docker installed, you can skip to step 5 to pull the image.

Step 1: Purchase and Activate a US Server

It is recommended to choose a server in the United States, because there are fewer or no restrictions. The server operating system can be a Linux series. The following takes Debian 12 as an example, and uses Yecaoyun, which I personally use. The reason for choosing it is simple: it is cheap and relatively stable, which is enough for voice-over relay.

If you already have a European or American Linux server, you can skip this section and go directly to the next section. If not, please continue reading.

Open this link to the Yecaoyun website and select Products & Services -> US AMD VPS in the top navigation bar.

image.png

Then, select any one of the top four configurations, which should be sufficient.

image.png

I personally use the 29 yuan/month configuration.

Click the "Buy Now" button to enter the configuration page. Here, select the server operating system as Debian 12, set the server password, and keep the other settings as default.

image.png

After the payment is completed, wait a few minutes. After the server is created and started successfully, you need to set up the firewall and open port 7899. You can only connect to the service for dubbing after this port is open.

Step 2: Allow Port 7899 in the Firewall

If you plan to use a domain name and configure Nginx reverse proxy, you do not need to open the port. If you are not familiar with these, for simplicity, it is recommended to directly open the port.

The firewall settings interface varies from server to server and panel to panel. The following takes the Yecaoyun panel I use as an example, and other panels can be used for reference. If you know how to open the port, you can skip this section and go directly to the next section.

First, in "My Products & Services", click the product you just activated to enter the product information and management page.

image.png

image.png

On this page, you can find the server's IP address, password, and other information.

image.png

Find "Firewall" under "Additional Tools" and click to open it.

image.png

Then allow port 7899, as shown below:

image.png

Step 3: Connect to the Terminal and Log in to the Server

If you already know how to connect to the terminal, or have other SSH terminals such as Xshell, you can skip this step and go directly to the next section.

On the product information page, find Xterm.js Console and click it. Then follow the instructions below:

image.png

image.png

When the above picture appears, press Enter a few times.

When Login: is displayed, enter root after it, and then press Enter. image.png

Then Password: will appear. Now you need to paste the password you copied (if you forgot it, you can find it on the product information page).

Note: Do not use Ctrl+V or right-click to paste, as this may cause extra spaces or line breaks to be entered, resulting in an incorrect password.

image.png

Hold down the Shift key + Insert key to paste the password to prevent the password from being correct but unable to log in, and then press Enter.

image.png

A successful login is shown below.

image.png

Step 4: Install Docker

If your server already has Docker installed or you know how to install it, you can skip this step.

Execute the following 5 commands in sequence. Note that you should execute the next command after each command is executed successfully. These commands are only applicable to the Debian 12 series servers.

After [root@xxxxxx~]#, right-click to paste the following command, and press Enter to execute it after pasting.

image.png

Command 1: sudo apt update && sudo apt install -y apt-transport-https ca-certificates curl gnupg

Command 2: curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

Command 3: echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/debian $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

Command 4: sudo apt update && sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin

Command 5: Start the Docker service. sudo systemctl start docker && sudo systemctl enable docker && sudo usermod -aG docker $USER

image.png

This command can be pasted by right-clicking. After pasting, press the Enter key.

Step 5: Pull the edge-tts-api Image and Start the API Service

Enter the following command to automatically pull the image and start the service. After the startup is successful, you can use it in video translation software or other tools that support OpenAI TTS.

docker run -p 7899:7899 jianchang512/edge-tts-api:latest

image.png

Press Ctrl+C continuously to stop the service.

Note that this command will run in the foreground. If you close the terminal window, the service will stop.

You can use the following command instead to start the service in the background. You can safely close the terminal after execution.

docker run -d -p 7899:7899 jianchang512/edge-tts-api:latest

image.png

If there are no errors, it means that the startup is successful. You can open http://your_ip:7899/v1/audio/speech in your browser to verify. If the result similar to the figure below appears, it means that the startup is successful.

image.png

Using in Video Translation Software

Please upgrade the software to v3.40 before use. The upgrade download address is https://pyvideotrans.com/downpackage

Open the menu and go to TTS Settings -> OpenAI TTS and change the interface address to http://your_ip:7899/v1

SK can be filled in arbitrarily, as long as it is not empty. In the role list, separate the roles you want to use with commas.

image.png

Available Roles

The following is a list of available roles. Note that the text language and role must match.

image.png

Chinese Pronunciation Roles:
    zh-HK-HiuGaaiNeural
    zh-HK-HiuMaanNeural
    zh-HK-WanLungNeural
    zh-CN-XiaoxiaoNeural
    zh-CN-XiaoyiNeural
    zh-CN-YunjianNeural
    zh-CN-YunxiNeural
    zh-CN-YunxiaNeural
    zh-CN-YunyangNeural
    zh-CN-liaoning-XiaobeiNeural
    zh-TW-HsiaoChenNeural
    zh-TW-YunJheNeural
    zh-TW-HsiaoYuNeural
    zh-CN-shaanxi-XiaoniNeural

English Roles:
    en-AU-NatashaNeural
    en-AU-WilliamNeural
    en-CA-ClaraNeural
    en-CA-LiamNeural
    en-HK-SamNeural
    en-HK-YanNeural
    en-IN-NeerjaExpressiveNeural
    en-IN-NeerjaNeural
    en-IN-PrabhatNeural
    en-IE-ConnorNeural
    en-IE-EmilyNeural
    en-KE-AsiliaNeural
    en-KE-ChilembaNeural
    en-NZ-MitchellNeural
    en-NZ-MollyNeural
    en-NG-AbeoNeural
    en-NG-EzinneNeural
    en-PH-JamesNeural
    en-PH-RosaNeural
    en-SG-LunaNeural
    en-SG-WayneNeural
    en-ZA-LeahNeural
    en-ZA-LukeNeural
    en-TZ-ElimuNeural
    en-TZ-ImaniNeural
    en-GB-LibbyNeural
    en-GB-MaisieNeural
    en-GB-RyanNeural
    en-GB-SoniaNeural
    en-GB-ThomasNeural
    en-US-AvaMultilingualNeural
    en-US-AndrewMultilingualNeural
    en-US-EmmaMultilingualNeural
    en-US-BrianMultilingualNeural
    en-US-AvaNeural
    en-US-AndrewNeural
    en-US-EmmaNeural
    en-US-BrianNeural
    en-US-AnaNeural
    en-US-AriaNeural
    en-US-ChristopherNeural
    en-US-EricNeural
    en-US-GuyNeural
    en-US-JennyNeural
    en-US-MichelleNeural
    en-US-RogerNeural
    en-US-SteffanNeural

Japanese Roles:
    ja-JP-KeitaNeural
    ja-JP-NanamiNeural

Korean Roles:
    ko-KR-HyunsuNeural
    ko-KR-InJoonNeural
    ko-KR-SunHiNeural

French Roles:
    fr-BE-CharlineNeural
    fr-BE-GerardNeural
    fr-CA-ThierryNeural
    fr-CA-AntoineNeural
    fr-CA-JeanNeural
    fr-CA-SylvieNeural
    fr-FR-VivienneMultilingualNeural
    fr-FR-RemyMultilingualNeural
    fr-FR-DeniseNeural
    fr-FR-EloiseNeural
    fr-FR-HenriNeural
    fr-CH-ArianeNeural
    fr-CH-FabriceNeural

German Roles:
    de-AT-IngridNeural
    de-AT-JonasNeural
    de-DE-SeraphinaMultilingualNeural
    de-DE-FlorianMultilingualNeural
    de-DE-AmalaNeural
    de-DE-ConradNeural
    de-DE-KatjaNeural
    de-DE-KillianNeural
    de-CH-JanNeural
    de-CH-LeniNeural

Spanish Roles:
    es-AR-ElenaNeural
    es-AR-TomasNeural
    es-BO-MarceloNeural
    es-BO-SofiaNeural
    es-CL-CatalinaNeural
    es-CL-LorenzoNeural
    es-ES-XimenaNeural
    es-CO-GonzaloNeural
    es-CO-SalomeNeural
    es-CR-JuanNeural
    es-CR-MariaNeural
    es-CU-BelkysNeural
    es-CU-ManuelNeural
    es-DO-EmilioNeural
    es-DO-RamonaNeural
    es-EC-AndreaNeural
    es-EC-LuisNeural
    es-SV-LorenaNeural
    es-SV-RodrigoNeural
    es-GQ-JavierNeural
    es-GQ-TeresaNeural
    es-GT-AndresNeural
    es-GT-MartaNeural
    es-HN-CarlosNeural
    es-HN-KarlaNeural
    es-MX-DaliaNeural
    es-MX-JorgeNeural
    es-NI-FedericoNeural
    es-NI-YolandaNeural
    es-PA-MargaritaNeural
    es-PA-RobertoNeural
    es-PY-MarioNeural
    es-PY-TaniaNeural
    es-PE-AlexNeural
    es-PE-CamilaNeural
    es-PR-KarinaNeural
    es-PR-VictorNeural
    es-ES-AlvaroNeural
    es-ES-ElviraNeural
    es-US-AlonsoNeural
    es-US-PalomaNeural
    es-UY-MateoNeural
    es-UY-ValentinaNeural
    es-VE-PaolaNeural
    es-VE-SebastianNeural

Arabic Roles:
    ar-DZ-AminaNeural
    ar-DZ-IsmaelNeural
    ar-BH-AliNeural
    ar-BH-LailaNeural
    ar-EG-SalmaNeural
    ar-EG-ShakirNeural
    ar-IQ-BasselNeural
    ar-IQ-RanaNeural
    ar-JO-SanaNeural
    ar-JO-TaimNeural
    ar-KW-FahedNeural
    ar-KW-NouraNeural
    ar-LB-LaylaNeural
    ar-LB-RamiNeural
    ar-LY-ImanNeural
    ar-LY-OmarNeural
    ar-MA-JamalNeural
    ar-MA-MounaNeural
    ar-OM-AbdullahNeural
    ar-OM-AyshaNeural
    ar-QA-AmalNeural
    ar-QA-MoazNeural
    ar-SA-HamedNeural
    ar-SA-ZariyahNeural
    ar-SY-AmanyNeural
    ar-SY-LaithNeural
    ar-TN-HediNeural
    ar-TN-ReemNeural
    ar-AE-FatimaNeural
    ar-AE-HamdanNeural
    ar-YE-MaryamNeural
    ar-YE-SalehNeural
 
Bengali Roles:
    bn-BD-NabanitaNeural
    bn-BD-PradeepNeural
    bn-IN-BashkarNeural
    bn-IN-TanishaaNeural

Czech Roles
    cs-CZ-AntoninNeural
    cs-CZ-VlastaNeural

Dutch Roles:
    nl-BE-ArnaudNeural
    nl-BE-DenaNeural
    nl-NL-ColetteNeural
    nl-NL-FennaNeural
    nl-NL-MaartenNeural

Hebrew Roles:
    he-IL-AvriNeural
    he-IL-HilaNeural

Hindi Roles:
    hi-IN-MadhurNeural
    hi-IN-SwaraNeural

Hungarian Roles:
    hu-HU-NoemiNeural
    hu-HU-TamasNeural

Indonesian Roles:
    id-ID-ArdiNeural
    id-ID-GadisNeural

Italian Roles:
    it-IT-GiuseppeNeural
    it-IT-DiegoNeural
    it-IT-ElsaNeural
    it-IT-IsabellaNeural

Kazakh Roles:
    kk-KZ-AigulNeural
    kk-KZ-DauletNeural
    
Malay Roles:
    ms-MY-OsmanNeural
    ms-MY-YasminNeural

Polish Roles:
    pl-PL-MarekNeural
    pl-PL-ZofiaNeural

Portuguese Roles:
    pt-BR-ThalitaNeural
    pt-BR-AntonioNeural
    pt-BR-FranciscaNeural
    pt-PT-DuarteNeural
    pt-PT-RaquelNeural

Russian Roles:
    ru-RU-DmitryNeural
    ru-RU-SvetlanaNeural

Swedish Roles:
    sw-KE-RafikiNeural
    sw-KE-ZuriNeural
    sw-TZ-DaudiNeural
    sw-TZ-RehemaNeural

Thai Roles:
    th-TH-NiwatNeural
    th-TH-PremwadeeNeural

Turkish Roles:
    tr-TR-AhmetNeural
    tr-TR-EmelNeural

Ukrainian Roles:
    uk-UA-OstapNeural
    uk-UA-PolinaNeural

Vietnamese Roles:
    vi-VN-HoaiMyNeural
    vi-VN-NamMinhNeural

Using in OpenAI SDK

You need to install the openai library pip install openai

from openai import OpenAI

client = OpenAI(api_key='12314', base_url='http://your_ip:7899/v1')
with  client.audio.speech.with_streaming_response.create(
                    model='tts-1',
                    voice='zh-CN-YunxiNeural',
                    input='Hello, dear friends',
                    speed=1.0                    
                ) as response:
    with open('./test.mp3', 'wb') as f:
       for chunk in response.iter_bytes():
            f.write(chunk)

Directly Using Requests for Calls

import requests
res=requests.post('http://your_ip:7899/v1',data={"voice":"zh-CN-YunxiNeural",
                    "input":"Hello, dear friends",
                    speed=1.0 })
with open('./test.mp3', 'wb') as f:
    f.write(res.content)