Spaces:
Running
Running
File size: 5,517 Bytes
6704495 54199ed 6704495 0d9591f 479fe9d 36ce10c 0d9591f 36ce10c 0d9591f 480bcab c433823 0d9591f 36ce10c 6704495 36ce10c 0d9591f 6704495 36ce10c 6704495 296c0e9 6704495 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 |
import gradio as gr
import requests
import json
import os
import time
from collections import defaultdict
BASE_URL = "https://api.jigsawstack.com/v1"
headers = {
"x-api-key": os.getenv("JIGSAWSTACK_API_KEY")
}
# Rate limiting configuration
request_times = defaultdict(list)
MAX_REQUESTS = 20 # Maximum requests per time window
TIME_WINDOW = 3600 # Time window in seconds (1 hour)
def get_real_ip(request: gr.Request):
"""Extract real IP address using x-forwarded-for header or fallback"""
if not request:
return "unknown"
forwarded = request.headers.get("x-forwarded-for")
if forwarded:
ip = forwarded.split(",")[0].strip() # First IP in the list is the client's
else:
ip = request.client.host # fallback
return ip
def check_rate_limit(request: gr.Request):
"""Check if the current request exceeds rate limits"""
if not request:
return True, "Rate limit check failed - no request info"
ip = get_real_ip(request)
now = time.time()
# Clean up old timestamps outside the time window
request_times[ip] = [t for t in request_times[ip] if now - t < TIME_WINDOW]
# Check if rate limit exceeded
if len(request_times[ip]) >= MAX_REQUESTS:
time_remaining = int(TIME_WINDOW - (now - request_times[ip][0]))
time_remaining_minutes = round(time_remaining / 60, 1)
time_window_minutes = round(TIME_WINDOW / 60, 1)
return False, f"Rate limit exceeded. You can make {MAX_REQUESTS} requests per {time_window_minutes} minutes. Try again in {time_remaining_minutes} minutes."
# Add current request timestamp
request_times[ip].append(now)
return True, ""
def transcribe_audio(input_type, audio_url, file_store_key, language, request: gr.Request):
"""Transcribe audio using JigsawStack Speech-to-Text API"""
# Check rate limit first
rate_limit_ok, rate_limit_msg = check_rate_limit(request)
if not rate_limit_ok:
return rate_limit_msg, ""
if input_type == "Audio URL" and not audio_url:
return "Error: Please provide an audio URL.", ""
if input_type == "File Store Key" and not file_store_key:
return "Error: Please provide a file store key.", ""
try:
payload = {}
if input_type == "Audio URL":
payload["url"] = audio_url.strip()
if input_type == "File Store Key":
payload["file_store_key"] = file_store_key.strip()
if language:
payload["language"] = language
response = requests.post(
f"{BASE_URL}/ai/transcribe",
headers=headers,
json=payload
)
response.raise_for_status()
result = response.json()
if not result.get("success"):
error_msg = f"Error: API call failed - {result.get('message', 'Unknown error')}"
return error_msg, ""
transcribed_text = result.get("text", "")
return "Transcription completed successfully!", transcribed_text
except requests.exceptions.RequestException as e:
return f"Request failed: {str(e)}", ""
except Exception as e:
return f"An unexpected error occurred: {str(e)}", ""
with gr.Blocks() as demo:
gr.Markdown("""
<div style='text-align: center; margin-bottom: 24px;'>
<h1 style='font-size:2.2em; margin-bottom: 0.2em;'>🧩 Speech-to-Text Transcription</h1>
<p style='font-size:1.2em; margin-top: 0;'>Convert speech to text with ease.</p>
<p style='font-size:1em; margin-top: 0.5em;'>For more details and API usage, see the <a href='https://jigsawstack.com/docs/api-reference/ai/speech-to-text' target='_blank'>documentation</a>.</p>
</div>
""")
with gr.Row():
with gr.Column():
gr.Markdown("#### Audio Input")
input_type = gr.Radio([
"Audio URL",
"File Store Key"
], value="Audio URL", label="Select Input Type")
audio_url = gr.Textbox(
label="Audio URL",
placeholder="Enter the URL of the audio/video file...",
visible=True
)
file_store_key = gr.Textbox(
label="File Store Key",
placeholder="Enter the file store key from JigsawStack File Storage...",
visible=False
)
language = gr.Textbox(
label="Language (optional)",
placeholder="e.g., en, es, fr, de, ja, zh... (leave empty for auto-detect)"
)
transcribe_btn = gr.Button("Start Transcription", variant="primary")
with gr.Column():
gr.Markdown("#### Transcription Result")
status_message = gr.Textbox(label="Status", interactive=False)
transcribed_text = gr.Textbox(
label="Transcribed Text",
interactive=False,
lines=10,
max_lines=20
)
def toggle_inputs(selected):
if selected == "Audio URL":
return gr.update(visible=True), gr.update(visible=False)
else:
return gr.update(visible=False), gr.update(visible=True)
input_type.change(toggle_inputs, inputs=[input_type], outputs=[audio_url, file_store_key])
transcribe_btn.click(
transcribe_audio,
inputs=[input_type, audio_url, file_store_key, language],
outputs=[status_message, transcribed_text]
)
demo.launch()
|