Spaces:
Running
Running
""" | |
Copyright 2023 Balacoon | |
Voice Conversion service interactive demo | |
""" | |
import glob | |
import logging | |
import os | |
import socket | |
from typing import Dict | |
import gradio as gr | |
from vc_service_request import vc_service_request | |
script_dir = os.path.dirname(os.path.abspath(__file__)) | |
counter = 0 | |
# dict to limit max numer of usages per user without API key | |
# clears up on demo restart, but thats ok for now | |
users: Dict[str, int] = {} | |
FREE_TIER = 3 | |
def get_ip(request: gr.Request) -> str: | |
""" | |
returns user IP from request | |
as in https://huggingface.co/spaces/radames/gradio-request-get-client-ip/blob/main/app.py | |
""" | |
client_ip = request.client.host | |
local_ip = socket.gethostbyname(socket.gethostbyname("")) | |
headers = request.kwargs['headers'] | |
if headers and 'x-forwarded-for' in headers: | |
x_forwarded_for = headers['x-forwarded-for'] | |
client_ip = x_forwarded_for.split(' ')[0] if x_forwarded_for else "" | |
return client_ip | |
def main(): | |
logging.basicConfig(level=logging.INFO) | |
badges = """ | |
<div style="display: flex"> | |
<span style="margin-right: 5px"> | |
[<img src="https://play.google.com/intl/en_us/badges/static/images/badges/en_badge_web_generic.png" width="200" height="77">](https://play.google.com/store/apps/details?id=com.app.vc) | |
</span> | |
</div> | |
""" | |
with gr.Blocks() as demo: | |
gr.Markdown( | |
""" | |
<h1 align="center">Balacoon🦝 Voice Conversion</h1> | |
Welcome to the live demo of Balacoon's Voice Conversion service. | |
Check out our [website](https://balacoon.com/demo/#voice-conversion) | |
to learn more. | |
Voice Conversion allows you to transform your own voice | |
into the voice of another person using just a single sample. | |
For optimal results, we recommend using clean audio files in English. | |
Here's how it works: | |
1. Begin by recording your voice. | |
2. Select an audio sample that represents the target voice you want to convert to. | |
3. Click the "Convert" button and listen to the result! | |
If providing your own audio files, please use WAVE PCM. | |
Service works with 16kHz, 16 bit, mono audio. | |
If you are interested to plug in Voice Conversion | |
service into your own application, don't hesitate to get in touch with us at | |
[[email protected]](mailto:[email protected]) | |
""" | |
) | |
gr.Markdown(badges) | |
with gr.Row(): | |
apikey = gr.Textbox(label="API key", placeholder="Enter API key or leave empty for a free tier") | |
with gr.Row(): | |
apisecret = gr.Textbox(label="API secret", placeholder="Enter API secret or leave empty for a free tier") | |
with gr.Row(): | |
with gr.Column(variant="panel"): | |
src_audio_mic = gr.Audio(source="microphone", label="Record your voice") | |
src_audio_file = gr.Audio( | |
source="upload", label="Or upload audio to convert" | |
) | |
with gr.Column(variant="panel"): | |
tgt_audio_file = gr.Audio( | |
source="upload", label="Select audio with target voice" | |
) | |
tgt_examples_paths = glob.glob( | |
os.path.join(script_dir, "references", "*.wav") | |
) | |
gr.Examples( | |
tgt_examples_paths, | |
inputs=[tgt_audio_file], | |
) | |
with gr.Row(): | |
convert_btn = gr.Button("Convert") | |
with gr.Row(): | |
result_audio = gr.Audio() | |
def voice_conversion(src_from_mic_, src_from_file_, tgt_from_file_, api_key_, api_secret_, request_: gr.Request): | |
""" | |
helper function which checks where source come from | |
""" | |
src_ = None | |
if src_from_mic_: | |
src_ = src_from_mic_ | |
elif src_from_file_: | |
src_ = src_from_file_ | |
tgt_ = tgt_from_file_ | |
if not src_ or not tgt_: | |
logging.warning("source or target are not provided") | |
gr.Warning("Source or target audio are not provided") | |
return | |
global counter, users | |
ip_ = get_ip(request_) | |
past_requests_ = users.get(ip_, 0) | |
free_tier_ = False | |
if not api_key_ or not api_secret_: | |
free_tier = True | |
api_key_ = os.environ["api_key"] | |
api_secret_ = os.environ["api_secret"] | |
if free_tier and past_requests_ >= FREE_TIER: | |
gr.Warning("Free tier exceeded, please reach out to get your API key") | |
logging.info(f"Free tier exceeded for {ip_}") | |
return None | |
logging.info(f"Total number of requests: {counter}. {past_requests_} for {ip_}") | |
counter += 1 | |
users[ip_] = past_requests_ + 1 | |
return vc_service_request(src_, tgt_, api_key_, api_secret_) | |
convert_btn.click( | |
voice_conversion, | |
inputs=[src_audio_mic, src_audio_file, tgt_audio_file, apikey, apisecret], | |
outputs=result_audio, | |
) | |
demo.queue(concurrency_count=1).launch() | |
if __name__ == "__main__": | |
main() | |