gradio-app / gradio

Build and share delightful machine learning apps, all in Python. 🌟 Star to support our work!
http://www.gradio.app
Apache License 2.0
33.41k stars 2.52k forks source link

Use Start/Stop button to record live audio using Gradio app #5425

Closed IshanRattan closed 1 year ago

IshanRattan commented 1 year ago

Hi All,

I need help with a problem. I want to add a button in my Gradio app to start/stop audio recording. Basically, what I am trying to do is place a button on the UI. When a user clicks on the this button(let’s say “Speak”), then audio recoding starts and the button text changes to “Stop”. When user clicks on the button again(which now says “Stop”) then audio recording stops.

I want something like this:

1

abidlabs commented 1 year ago

Hi @IshanRattan why not just use the default button built into the gr.Audio(source="microphone")?

IshanRattan commented 1 year ago

Hi @abidlabs , I need to hide the built in button and use one custom button to trigger multiple actions further, so a single button which changes its label on click and also starts recording would solve these challenges for me.

abidlabs commented 1 year ago

Hi @IshanRattan you can't hide the existing button, but what you can do is attach an event to the audio component's start_recording() and stop_recording() buttons, which allows you to connect multiple events to these steps. Here's an example:

import gradio as gr

def event():
    print("recording started")

def other_event():
    print("recording stopped")

with gr.Blocks() as demo:
    a = gr.Audio(source="microphone")
    a.start_recording(event, None, None)
    a.stop_recording(other_event, None, None)

demo.launch()
IshanRattan commented 1 year ago

Thanks but this doesn't solve the original problem of triggering .start_recording(). Thanks a lot for your effort though! Lastly, please do think of providing a customisable button for start/stop audio recording(in future releases). I'm sure it will help many other users.

IshanRattan commented 1 year ago

Working solution to the original prob:


import gradio as gr

def click_js():
    return """function audioRecord() {
    var xPathRes = document.evaluate ('//*[@id="audio"]//button', document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null); 
    xPathRes.singleNodeValue.click();}"""

def action(btn):
    """Changes button text on click"""
    if btn == 'Speak': return 'Stop'
    else: return 'Speak'

def check_btn(btn):
    """Checks for correct button text before invoking transcribe()"""
    if btn != 'Speak': raise Exception('Recording...')

def transcribe():
    return 'Success'

with gr.Blocks() as demo:
    msg = gr.Textbox()
    audio_box = gr.Audio(label="Audio", source="microphone", type="filepath", elem_id='audio')

    with gr.Row():
        audio_btn = gr.Button('Speak')
        clear = gr.Button("Clear")

    audio_btn.click(fn=action, inputs=audio_btn, outputs=audio_btn).\
              then(fn=lambda: None, _js=click_js()).\
              then(fn=check_btn, inputs=audio_btn).\
              success(fn=transcribe, outputs=msg)

    clear.click(lambda: None, None, msg, queue=False)

demo.queue().launch(debug=True)