File size: 1,850 Bytes
6f9faf9
 
379cab9
bd6580c
6f9faf9
379cab9
7e0b27a
 
 
 
 
 
 
6f9faf9
 
7e0b27a
 
 
6f9faf9
 
7e0b27a
 
 
 
 
 
 
 
 
6f9faf9
7e0b27a
 
 
 
 
6f9faf9
 
bd6580c
6f9faf9
 
7e0b27a
 
 
 
 
 
6f9faf9
 
 
7e0b27a
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
import numpy as np
import gradio as gr
import spaces
from fastrtc import WebRTC, get_turn_credentials

@spaces.GPU
def flip_frame_handler(video_frame):
    """
    Flips the incoming video frame vertically and yields it.
    This needs to be a generator function because the output is a receive-only stream.
    """
    if video_frame:
        yield np.flip(video_frame, axis=0)

# --- Gradio UI Layout ---
with gr.Blocks(theme=gr.themes.Soft(), title="FastRTC Webcam Frame Flipper") as demo:
    gr.Markdown("# 🚀 FastRTC Webcam Frame Flipper (Side-by-Side)")
    gr.Markdown("*This demo takes your webcam feed from the left panel, flips each frame vertically on the server, and streams it back to the right panel in real-time.*")
    
    with gr.Row():
        with gr.Column():
            gr.Markdown("### 1. Your Webcam Feed (Input)")
            # This component only sends video to the server
            webcam_input = WebRTC(
                label="Webcam Input",
                modality="video", 
                mode="send",
                rtc_configuration=get_turn_credentials(),
            )
            
        with gr.Column():
            gr.Markdown("### 2. Flipped Video (Output)")
            # This component only receives video from the server
            video_output = WebRTC(
                label="Flipped Output Stream",
                modality="video", 
                mode="receive",
                rtc_configuration=get_turn_credentials(),
            )
        
    # The `stream` event is triggered by the input component
    webcam_input.stream(
        fn=flip_frame_handler, 
        inputs=[webcam_input],      # Input is the webcam feed
        outputs=[video_output],     # Output is the separate receive-only component
        time_limit=60,
    )

if __name__ == "__main__":
    demo.queue().launch()