|
import gradio as gr |
|
import re |
|
import requests |
|
import time |
|
import tempfile |
|
import os |
|
|
|
token = os.environ['apikey'] |
|
API_HOST = "https://api.voicemod.net" |
|
|
|
|
|
|
|
def separate_syllables(string): |
|
|
|
numbers = [ 8, 9, 8, 9 ] |
|
|
|
parts = string.split(" ") |
|
string = "".join(parts) |
|
print("the new string: "+ string) |
|
chars = list(string) |
|
|
|
|
|
syllables = [] |
|
|
|
|
|
for num in numbers: |
|
|
|
syllable = "".join(chars[:num]) |
|
print("Appending " + "".join(chars[:num])) |
|
|
|
syllables.append(syllable) |
|
|
|
chars = chars[num:] |
|
|
|
|
|
if chars: |
|
syllables.append("-") |
|
for num in numbers: |
|
|
|
syllable = "".join(chars[:num]) |
|
|
|
syllables.append(syllable) |
|
|
|
chars = chars[num:] |
|
|
|
|
|
if("-" in syllables): |
|
results = [[]] |
|
lines = 0 |
|
for i ,v in enumerate(syllables): |
|
if v == '-': |
|
lines=lines+1 |
|
else: |
|
if(len(results) == 1): |
|
results.append([]) |
|
results[lines].append(v) |
|
|
|
return list(map(lambda words: " ".join(words), results)) |
|
else: |
|
return " ".join(syllables) |
|
|
|
|
|
def flattenLines(lyrics): |
|
newValues = [] |
|
for i,val in enumerate(lyrics): |
|
if(type(lyrics[i]) == list): |
|
newValues.append(lyrics[i][0]) |
|
newValues.append(lyrics[i][1]) |
|
else: |
|
newValues.append(lyrics[i]) |
|
|
|
return newValues |
|
|
|
def getPayload(index): |
|
print("Getting payload for index: " + str(index)) |
|
match index: |
|
case 0: |
|
return { |
|
"voiceModel":"CFV_2", |
|
"voiceModelStyle":"mezzo", |
|
"language":"en", |
|
"scoreFileRemotePath":"themes/DeckTheHalls/score/TTS_XMAS_DeckTheHalls_Melody_C_200bpm_4x4_ABCD.json", |
|
"scoreDataFileRemotePath":"themes/DeckTheHalls/score/TTS_XMAS_DeckTheHalls_Score_Data_ABCD.json", |
|
"dspFileRemotePath": "themes/DeckTheHalls/dsp/XML/TTS_XMAS_DeckTheHalls_DSP_C_200bpm_ABCD.xml", |
|
"lyrics": [], |
|
"dspEffect": "", |
|
"backgroundSounds":False, |
|
"artistName":"Cecilia", |
|
"songName":"Deck The Halls", |
|
"singerImageRemotePath":"singers/Singer-Cecilia-VideoImageBackground.png", |
|
"backgroundImageRemotePath":"themes/DeckTheHalls/images/Song-DeckTheHalls-VideoImageBackground02.png" |
|
} |
|
case 1: |
|
return { |
|
"voiceModel":"CFV_2", |
|
"voiceModelStyle":"mezzo", |
|
"language":"en", |
|
"scoreDataFileRemotePath": "themes/MoveYourBody/score/MoveYourBody_Score_Data_ABCD.json", |
|
"scoreFileRemotePath": "themes/MoveYourBody/score/MoveYourBody_Melody_ABCD.json", |
|
"singerImageRemotePath": "singers/Singer-Cecilia-VideoImageBackground.png", |
|
"dspFileRemotePath": "themes/MoveYourBody/dsp/XML/MoveYourBody_DSP_ABCD.xml", |
|
"dspEffect":"", |
|
"lyrics": [], |
|
"backgroundSounds":False, |
|
"artistName":"Cecilia", |
|
"songName":"Move Your Body", |
|
"backgroundImageRemotePath":"themes/DeckTheHalls/images/Song-DeckTheHalls-VideoImageBackground02.png" |
|
} |
|
|
|
case 2: |
|
return { |
|
"voiceModel": "Randy_v3o", |
|
"voiceModelStyle": "randy", |
|
"language": "en", |
|
"scoreFileRemotePath": "themes/DarkTrap/score/DarkTrap_Melody_ABCDEFGH.json", |
|
"scoreDataFileRemotePath": "themes/DarkTrap/score/DarkTrap_Score_Data_ABCDEFGH.json", |
|
"dspFileRemotePath": "themes/DarkTrap/dsp/XML/DarkTrap_DSP_ABCDEFGH.xml", |
|
"dspEffect": "", |
|
"lyrics": [], |
|
"backgroundSounds": False, |
|
"artistName": "Jerry", |
|
"songName": "Dark Trap", |
|
"singerImageRemotePath": "singers/Singer-Jerry-VideoImageBackground.png", |
|
"backgroundImageRemotePath": "themes/DeckTheHalls/images/Song-DeckTheHalls-VideoImageBackground01.png" |
|
} |
|
|
|
case 3: |
|
return { |
|
"artistName": "Jerry", |
|
"backgroundImageRemotePath": "themes/HappyBirthday/images/Song-HappyBirthday-VideoImageBackground01.png", |
|
"backgroundSounds": False, |
|
"dspEffect": "", |
|
"dspFileRemotePath": "themes/HappyBirthday/dsp/XML/HappyBirthday_DSP_ABCD.xml", |
|
"language": "en", |
|
"lyrics": [], |
|
"scoreDataFileRemotePath": "themes/HappyBirthday/score/HappyBirthday_Score_Data_ABCD.json", |
|
"scoreFileRemotePath": "themes/HappyBirthday/score/HappyBirthday_Melody_ABCD.json", |
|
"singerImageRemotePath": "singers/Singer-Jerry-VideoImageBackground.png", |
|
"songName": "Happy Birthday", |
|
"voiceModel": "CFV_2", |
|
"voiceModelStyle": "baritone" |
|
} |
|
|
|
case 4: |
|
return { |
|
"voiceModel": "Randy_v3o", |
|
"voiceModelStyle": "randy", |
|
"language": "en", |
|
"scoreFileRemotePath": "themes/Levitate/score/Levitate_Melody_ABCD.json", |
|
"scoreDataFileRemotePath": "themes/Levitate/score/Levitate_Score_Data_ABCD.json", |
|
"dspFileRemotePath": "themes/Levitate/dsp/XML/Levitate_DSP_ABCD.xml", |
|
"dspEffect": "", |
|
"lyrics": [], |
|
"backgroundSounds": False, |
|
"artistName": "Jerry", |
|
"songName": "Levitate", |
|
"singerImageRemotePath": "singers/Singer-Ed-VideoImageBackground.png", |
|
"backgroundImageRemotePath": "themes/Levitate/images/Song-Levitate-VideoImageBackground02.png" |
|
} |
|
|
|
|
|
def cleanUpLines(lines): |
|
return list(filter(None, lines)) |
|
|
|
|
|
def greet(index, lyrics): |
|
url = API_HOST + "/v2/cloud/partners/ttsing" |
|
verification_url = API_HOST + "/v2/cloud/partners/ttsing/" |
|
|
|
print("Calling api with "+ lyrics) |
|
print("URL: " + url) |
|
|
|
lines = cleanUpLines(lyrics.split("\n")) |
|
|
|
|
|
payload = getPayload(index) |
|
payload["lyrics"] = lines |
|
|
|
|
|
headers = { |
|
'x-api-key': token |
|
} |
|
|
|
|
|
print(payload) |
|
print("Before the call") |
|
response = requests.request("POST", url, headers=headers, json=payload) |
|
print("After the call...") |
|
jsonResp = response.json() |
|
print(response.text) |
|
jobID = jsonResp['jobId'] |
|
verification_url += jsonResp['jobId'] |
|
while(True): |
|
response = requests.request('GET', verification_url, headers=headers) |
|
print(response.text) |
|
print(jobID) |
|
jsonResp = response.json() |
|
if(jsonResp['status'] == 'failed'): |
|
return "" |
|
|
|
if('transformedAudioUrl' in jsonResp and jsonResp['transformedAudioUrl'] is not None): |
|
return gr.make_waveform(download_file(jsonResp['transformedAudioUrl'])) |
|
|
|
print("Still processing...") |
|
time.sleep(1) |
|
|
|
|
|
|
|
|
|
def download_file(url): |
|
response = requests.get(url) |
|
if response.status_code == 200: |
|
with tempfile.NamedTemporaryFile(delete=False) as tmp_file: |
|
tmp_file.write(response.content) |
|
tmp_file.flush() |
|
return tmp_file.name |
|
else: |
|
print("Error: Unable to download file") |
|
|
|
|
|
with gr.Blocks() as demo: |
|
|
|
|
|
|
|
gr.Markdown(""" |
|
## Voicemod's Text-to-Sing API |
|
To use this API follow the instructions: |
|
1. First, select the melody you want from the dropdown |
|
2. Then write the lyrics for it |
|
|
|
### Disclaimer |
|
Each melody has specific requirements for the lyrics (number of notes per verse and duration of each note). |
|
|
|
Use the examples provided to understand how they work and write valid lyrics to get best results |
|
|
|
Also, the length of the song is fixed, if you go over the line numbers the extra lyrics will be ignored. |
|
|
|
## Join our Community |
|
If you'd like to know more and meet other developers working with this technology, join our [Discord Server](https://discord.gg/vm-dev-community)! |
|
|
|
""") |
|
|
|
music_options = ["Deck the Halls by Cecilia", |
|
"Move your Body by Cecilia", |
|
"Dark Trap by Jerry", |
|
"Happy Birthday by Jerry", |
|
"Levitate by Ed"] |
|
|
|
with gr.Row(): |
|
with gr.Column(): |
|
with gr.Row(): |
|
dd = gr.Dropdown(choices=music_options, type="index", label="Select the melody...") |
|
lines = gr.Textbox(lines=10, placeholder="Write your lyrics here...", label="Lyrics") |
|
|
|
with gr.Row(): |
|
btn = gr.Button("Run") |
|
with gr.Column(): |
|
video = gr.Video(label="Generated output") |
|
video.style(height=300) |
|
|
|
gr.Markdown(""" |
|
## Example lyrics |
|
|
|
To make your life easier, while testing the API, you can use and modify the following lyrics for each song: |
|
""") |
|
|
|
gr.Examples(fn=greet, |
|
examples=[["Move your Body by Cecilia", """this is just a test |
|
don’t worry now |
|
the lyrics will come the less you think about them |
|
just feel the melody""" |
|
], |
|
["Dark Trap by Jerry","""this is just a test |
|
don't worry about what I say |
|
the lyrics want to go crazy |
|
when pushed too hard |
|
take it easy and relax |
|
this is moving too fast |
|
I can help you be |
|
a better singer""" |
|
], |
|
["Happy Birthday by Jerry","""happy birthday to you |
|
happy birthday to you! |
|
happy birthday dear Laura |
|
happy birthday to you!"""] , |
|
["Deck the Halls by Cecilia", """Deck the halls with boughs of holly |
|
Fa la la la la, la la la la |
|
'Tis the season to be jolly |
|
Fa la la la la, la la la la""" ], |
|
["Levitate by Ed", """this is just a test |
|
don’t worry about what I say |
|
the lyrics want to go crazy |
|
when pushed too hard"""] |
|
|
|
], |
|
inputs=[ |
|
dd, |
|
lines |
|
], |
|
outputs=video, |
|
cache_examples=True |
|
) |
|
|
|
|
|
gr.Markdown(""" |
|
## Want to use this API for your project? |
|
|
|
If you'd like to use this API for your own project, request access through our [form here](https://voicemod.typeform.com/to/KqeNN6bO?typeform-source=huggingface) and join |
|
our [Dev Community on Discord](https://discord.gg/vm-dev-community)! |
|
""") |
|
|
|
btn.click(fn=greet, |
|
inputs=[ |
|
dd, |
|
lines |
|
], |
|
outputs=video) |
|
|
|
demo.launch() |
|
|