Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| from fastapi import FastAPI, Request | |
| from starlette.responses import JSONResponse | |
| import subprocess | |
| import uvicorn | |
| import threading | |
| # Inicializar la aplicaci贸n FastAPI | |
| app = FastAPI() | |
| # Estado para almacenar el proceso de FFmpeg | |
| app.state.ffmpeg_process = None | |
| # Funci贸n para iniciar FFmpeg | |
| def start_ffmpeg(rtmp_server, stream_key): | |
| # Comando FFmpeg para recibir video desde stdin y transmitir a RTMP | |
| command = [ | |
| "ffmpeg", | |
| "-re", | |
| "-i", "-", # Leer desde stdin | |
| "-c:v", "libx264", | |
| "-b:v", "1000k", | |
| "-f", "flv", | |
| f"{rtmp_server}/{stream_key}" | |
| ] | |
| process = subprocess.Popen(command, stdin=subprocess.PIPE) | |
| return process | |
| # Ruta de FastAPI para recibir el stream de video | |
| async def save_stream(request: Request): | |
| data = await request.body() | |
| if app.state.ffmpeg_process: | |
| try: | |
| app.state.ffmpeg_process.stdin.write(data) | |
| app.state.ffmpeg_process.stdin.flush() | |
| except BrokenPipeError: | |
| return JSONResponse({"status": "ffmpeg process not available"}, status_code=500) | |
| return JSONResponse({"status": "ok"}) | |
| # Funci贸n de Gradio para iniciar la transmisi贸n | |
| def start_streaming(rtmp_server, stream_key): | |
| if app.state.ffmpeg_process is None: | |
| process = start_ffmpeg(rtmp_server, stream_key) | |
| app.state.ffmpeg_process = process | |
| return "Transmisi贸n en vivo iniciada" | |
| else: | |
| return "La transmisi贸n ya est谩 en curso" | |
| # Crear la interfaz de Gradio | |
| with gr.Blocks() as demo: | |
| gr.Markdown("# Transmisi贸n en Vivo") | |
| with gr.Row(): | |
| rtmp_server = gr.Textbox(label="Servidor RTMP (YouTube, Twitch, etc.)", placeholder="rtmp://servidor/live", lines=1) | |
| stream_key = gr.Textbox(label="Clave de transmisi贸n", placeholder="Ingresa tu clave de transmisi贸n", type="password", lines=1) | |
| start_button = gr.Button("Iniciar Transmisi贸n") | |
| output = gr.Textbox(label="Estado", interactive=False) | |
| start_button.click(start_streaming, inputs=[rtmp_server, stream_key], outputs=output) | |
| # Agregar HTML y JavaScript para capturar la pantalla | |
| gr.HTML(""" | |
| <video id="screenPreview" style="display:none;"></video> | |
| <button onclick="startScreenCapture()">Compartir Pantalla</button> | |
| <script> | |
| async function startScreenCapture() { | |
| try { | |
| const stream = await navigator.mediaDevices.getDisplayMedia({ | |
| video: { cursor: "always" }, | |
| audio: false | |
| }); | |
| const videoElement = document.getElementById('screenPreview'); | |
| if (videoElement) { | |
| videoElement.srcObject = stream; | |
| videoElement.play(); | |
| } | |
| const mediaRecorder = new MediaRecorder(stream, { mimeType: 'video/webm; codecs=vp8' }); | |
| mediaRecorder.ondataavailable = function(event) { | |
| if (event.data.size > 0) { | |
| fetch('/save_stream', { | |
| method: 'POST', | |
| body: event.data | |
| }); | |
| } | |
| }; | |
| mediaRecorder.start(1000); // Enviar datos cada segundo | |
| } catch (err) { | |
| console.error("Error capturando pantalla: ", err); | |
| } | |
| } | |
| </script> | |
| """) | |
| # Montar la aplicaci贸n de Gradio en FastAPI | |
| app = gr.mount_gradio_app(app, demo, path="/") | |
| # Ejecutar la aplicaci贸n con Uvicorn | |
| if __name__ == "__main__": | |
| uvicorn.run(app, host="0.0.0.0", port=7860) |