Skip to content

gstream is a real-time video streaming platform built with ASP.NET Core 9, SignalR, WebRTC, and Redis. It supports secure one-to-one and one-to-many video communication with JWT and API key authentication. Includes a modern Tailwind UI, Redis-backed state, and cross-platform .NET support.

Notifications You must be signed in to change notification settings

ewceniza9009/gstream

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

gstream

gstream is a real-time video streaming application built with ASP.NET Core, SignalR, and WebRTC. It supports one-to-one video streaming and one-to-many broadcasting, using Redis for state management and JWT/API key authentication.


✨ Features

  • πŸš€ Scalable Broadcasting via LiveKit SFU (Self Hosted), allowing a single broadcaster to stream to a large audience with minimal client-side load.
  • πŸ’¬ Live Chat for real-time interaction during broadcasts.
  • πŸ“‘ Dual Broadcasting Modes: Choose between a simple peer-to-peer mesh for small groups or a powerful SFU for large audiences.
  • πŸ”— One-to-one video streaming via WebRTC and SignalR.
  • πŸ” JWT-based user authentication for broadcasters.
  • πŸ’… Responsive UI with Tailwind CSS.
  • ⚑ Real-time communication with SignalR and Redis.
  • 🌐 Cross-platform support with .NET 9.0.

πŸ“ Project Structure

gstream/
β”œβ”€β”€ Authentication/                 # Handles custom authentication logic
β”‚   └── ApiKeyAuth.cs              # Implements API key-based authentication for consumers
β”‚
β”œβ”€β”€ Controllers/                   # Manages incoming HTTP requests and API endpoints
β”‚   β”œβ”€β”€ AdminController.cs         # Admin dashboard API (user/room management)
β”‚   β”œβ”€β”€ AuthController.cs          # Handles user login, registration, password changes
β”‚   β”œβ”€β”€ BroadcastController.cs     # Starts, joins, and records broadcasts
β”‚   β”œβ”€β”€ RoomController.cs          # CRUD operations for rooms
β”‚   └── UserController.cs          # User-specific APIs (e.g., manage API keys)
β”‚
β”œβ”€β”€ Hubs/                          # SignalR hubs for real-time communication
β”‚   β”œβ”€β”€ BroadcastHub.cs            # Manages WebSocket for multi-viewer broadcasts
β”‚   └── StreamingHub.cs            # WebSocket hub for one-on-one video calls
β”‚
β”œβ”€β”€ Migrations/                    # EF Core database schema changes
β”‚
β”œβ”€β”€ Models/                        # Application data models and DTOs
β”‚   β”œβ”€β”€ Data/                      # EF models mapped to database tables
β”‚   β”‚   β”œβ”€β”€ ApplicationDbContext.cs # Main EF Core DbContext
β”‚   β”‚   β”œβ”€β”€ ChatMessage.cs         # Chat message table definition
β”‚   β”‚   β”œβ”€β”€ Room.cs                # Room table definition
β”‚   β”‚   └── User.cs                # User table definition
β”‚   β”œβ”€β”€ Mongo/                     # MongoDB models (if applicable)
β”‚   β”œβ”€β”€ ChangePasswordRequest.cs   # Model for change password API
β”‚   β”œβ”€β”€ ChatMessageDto.cs          # DTO for sending chat messages to clients
β”‚   β”œβ”€β”€ LoginRequest.cs            # Model for login/registration API
β”‚   β”œβ”€β”€ RoomDtp.cs                 # DTO for sending room data to clients
β”‚   β”œβ”€β”€ RoomRequest.cs             # Model for room creation/update
β”‚   └── UserModel.cs               # Admin panel user model
β”‚
β”œβ”€β”€ Properties/
β”‚   └── launchSettings.json        # Configurations for local development
β”‚
β”œβ”€β”€ Services/                      # Business logic and service layer
β”‚   β”œβ”€β”€ IBroadcastStateService.cs  # Broadcast state service interface
β”‚   β”œβ”€β”€ IRoomService.cs            # Room service interface
β”‚   β”œβ”€β”€ IUserService.cs            # User service interface
β”‚   β”œβ”€β”€ LiveKitService.cs          # Integration with LiveKit SFU server
β”‚   β”œβ”€β”€ RedisBroadcastStateService.cs # Broadcast state management using Redis
β”‚   β”œβ”€β”€ RoomService.cs             # Implementation of room logic
β”‚   └── UserService.cs             # Implementation of user logic
β”‚
β”œβ”€β”€ wwwroot/                       # Static web assets (HTML, JS, CSS)
β”‚   β”œβ”€β”€ js/
β”‚   β”‚   β”œβ”€β”€ account.js             # My Account page logic
β”‚   β”‚   β”œβ”€β”€ admin.js               # Admin dashboard logic
β”‚   β”‚   β”œβ”€β”€ broadcast.js           # Broadcaster dashboard logic
β”‚   β”‚   β”œβ”€β”€ consumer.js            # Broadcast viewer page logic
β”‚   β”‚   └── streaming.js           # One-on-one streaming page logic
β”‚   β”œβ”€β”€ account.html               # My Account page
β”‚   β”œβ”€β”€ admin.html                 # Admin dashboard
β”‚   β”œβ”€β”€ broadcast.html             # Broadcaster main interface
β”‚   β”œβ”€β”€ consumer.html              # Broadcast viewer interface
β”‚   β”œβ”€β”€ index.html                 # Main landing page
β”‚   └── streaming.html             # One-on-one call page
β”‚
β”œβ”€β”€ gstream.csproj                 # Main C# project file
β”œβ”€β”€ gstream.http                   # HTTP client requests for testing APIs
β”œβ”€β”€ gstream.sln                    # Visual Studio solution file
└── Program.cs                     # ASP.NET Core entry point and service configuration

βš™οΈ Prerequisites

  • .NET 9.0 SDK
  • Redis (local or via connection string)
  • Web browser with WebRTC support (e.g., Chrome, Firefox, Edge)

πŸš€ Setup

  1. Clone the repository

    git clone <repository-url>
    cd gstream
  2. Configure Redis

    Edit appsettings.json:

    "ConnectionStrings": {
      "Redis": "localhost:6379"
    }
  3. Configure JWT

    "Jwt": {
      "Issuer": "gstream-api",
      "Audience": "gstream-clients",
      "Key": "<your-secure-key>"
    }
  4. Configure API Key

    "ApiKey": "<your-api-key>"
  5. Configure Public URL

    "PublicUrl": "http://localhost:5122"
  6. Restore dependencies

    dotnet restore
  7. Run the application

    dotnet run

🌐 Access the Application

  • One-to-one streaming:
    http://localhost:[Port#]

  • Broadcasting:
    http://localhost:[Port#]/broadcast.html

  • Broadcast consumer:
    http://localhost:[Port#]/consumer.html

  • Test credentials:
    Username: admin
    Password: adminpassword



Screenshots

1 2 3 4 5 6 image

Features

  • One-to-One Streaming: Uses a direct WebRTC peer-to-peer connection, with signaling brokered by SignalR.
  • One-to-Many Broadcasting (Mesh Mode): The broadcaster creates a direct WebRTC connection with every individual viewer. This is simple but limited by the broadcaster's upload bandwidth. Best for 1-2 viewers.
  • One-to-Many Broadcasting (SFU Mode): The broadcaster sends a single high-quality stream to the LiveKit SFU. The SFU then handles the heavy lifting of distributing that stream to all viewers. This method is highly efficient and scalable, allowing for a large audience.

πŸ§ͺ Usage

πŸŽ₯ One-to-One Streaming

  1. Go to index.html
  2. Log in with testuser / password
  3. Enter a Room ID
  4. Click Join Room

πŸ“’ Broadcasting

  1. Go to broadcast.html
  2. Log in with testuser / password
  3. Click Start Broadcast
  4. Enter a Room ID and begin streaming

πŸ‘€ Broadcast Consumer

  1. Go to consumer.html
  2. Enter your API Key and Room ID
  3. Click Find and View Stream

πŸ§ͺ How to Restream (Consumer Developer)

πŸŽ₯ Backend

// In the developer's own ASP.NET Core project
[ApiController]
[Route("api/stream-proxy")]
public class StreamProxyController : ControllerBase
{
    private readonly IHttpClientFactory _httpClientFactory;
    private const string GStreamApiUrl = "https://YOUR_GSTREAM_URL.com"; // Your service URL
    private const string MySecretApiKey = "gsk_...the_developers_secret_api_key"; // Their key to YOUR service
    private const string MyUsernameForGstream = "proxy-user"; // The display name they use

    public StreamProxyController(IHttpClientFactory httpClientFactory)
    {
        _httpClientFactory = httpClientFactory;
    }

    [HttpGet("join/{roomName}")]
    public async Task<IActionResult> JoinStream(string roomName)
    {
        var client = _httpClientFactory.CreateClient();
        
        // Step 1: Prepare the request to the original gstream service
        var request = new HttpRequestMessage(HttpMethod.Post, $"{GStreamApiUrl}/api/broadcast/join/{roomName}");
        request.Headers.Add("X-Api-Key", MySecretApiKey);

        var joinRequestBody = new { username = MyUsernameForGstream };
        request.Content = new StringContent(System.Text.Json.JsonSerializer.Serialize(joinRequestBody), System.Text.Encoding.UTF8, "application/json");

        // Step 2: Call your gstream service to get a temporary connection token
        var response = await client.SendAsync(request);

        if (!response.IsSuccessStatusCode)
        {
            return StatusCode((int)response.StatusCode, "Could not connect to the stream.");
        }

        // Step 3: Forward the successful response (containing the token) to your own user
        var responseBody = await response.Content.ReadAsStringAsync();
        return Content(responseBody, "application/json");
    }
}

πŸ“’ HTML/Javascript UI

<!DOCTYPE html>
<html>
<head>
    <title>Our Awesome Stream</title>
</head>
<body>
    <h1>Live Stream</h1>
    <video id="remoteVideo" autoplay playsinline style="width:100%"></video>

    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/livekit-client.umd.min.js"></script>
    <script>
        const remoteVideo = document.getElementById('remoteVideo');
        const roomName = 'Public Room 1'; // The room they want to restream

        async function connectToStream() {
            try {
                // Call OWN backend proxy,
                const response = await fetch(`/api/stream-proxy/join/${roomName}`);
                const connectionDetails = await response.json();

                // Use token received proxy to connect the LiveKit
                const livekitRoom = new LivekitClient.Room();
                await livekitRoom.connect(connectionDetails.liveKitUrl, connectionDetails.token);

                livekitRoom.on(LivekitClient.RoomEvent.TrackSubscribed, (track) => {
                    if (track.kind === 'video') {
                        const element = track.attach();
                        remoteVideo.srcObject = element.srcObject;
                    }
                });

            } catch (error) {
                console.error("Failed to connect to stream via proxy.", error);
            }
        }

        connectToStream();
    </script>
</body>
</html>

How to use IP Camera

To stream from an IP camera, you need to provide the camera's specific video stream URL, not just its IP address. This URL acts as a direct link to the camera's video feed. The most common formats for this are RTSP and MJPEG.

How a User Finds and Uses the Stream URL Find the Camera's IP Address: The user first needs to find the camera's local IP address on their network (e.g., 192.168.1.100). This is usually found by looking at the connected devices list in their Wi-Fi router's settings. Find the Stream Path: Every camera brand and model has a unique URL path for its video stream. The best way to find this is to search online for "[Camera Brand] [Camera Model] RTSP URL". For example, "Amcrest IP2M-841 RTSP URL". Combine and Authenticate: The final URL is a combination of the IP address, the stream path, and often a username and password for the camera itself.

Example Let's say a user has: Camera IP Address: 192.168.1.123 Camera Username: admin Camera Password: cam_password

After searching online, they find their camera's RTSP path is /cam/realmonitor?channel=1&subtype=0.

The final URL they would enter into the "IP Camera" input field in your application would be: rtsp://admin:[email protected]/cam/realmonitor?channel=1&subtype=0

Pro Tip: Users can test this URL in a media player like VLC (File -> Open Network Stream) to confirm it works before putting it into your application.


πŸ” Authentication

  • Users: JWT-based via AuthController
  • Consumers: API key-based via ApiKeyAuth

πŸ“‘ WebRTC and SignalR

  • WebRTC: Peer-to-peer media streaming using STUN servers
  • SignalR: Real-time signaling with Redis backplane

πŸ”§ Configuration Reference

appsettings.json

{
  "PublicUrl": "http://localhost:5122",
  "ConnectionStrings": {
    "Redis": "localhost:6379"
  },
  "Jwt": {
    "Issuer": "gstream-api",
    "Audience": "gstream-clients",
    "Key": "<your-secure-key>"
  },
  "ApiKey": "<your-api-key>"
}

πŸ›  Development

  • Swagger UI: Available at /swagger (in development mode)
  • HTTP Testing: Use gstream.http with REST Client
  • Tech Stack:
    • ASP.NET Core 9.0
    • SignalR
    • Redis
    • WebRTC
    • Livekit(For SFU)
    • Tailwind CSS
    • Swashbuckle

⚠️ Notes

  • Ensure camera/microphone permissions are granted in your browser.
  • Local video preview is mirrored.
  • Broadcasts expire after 4 hours.
  • Only one broadcaster per room is allowed.

πŸ“„ License

Distributed By: Erwin Wilson Ceniza

About

gstream is a real-time video streaming platform built with ASP.NET Core 9, SignalR, WebRTC, and Redis. It supports secure one-to-one and one-to-many video communication with JWT and API key authentication. Includes a modern Tailwind UI, Redis-backed state, and cross-platform .NET support.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published