Skip to content

Instantly share code, notes, and snippets.

@recursivecodes
Created April 3, 2025 14:30

Revisions

  1. recursivecodes created this gist Apr 3, 2025.
    217 changes: 217 additions & 0 deletions claude-ivs-broadcasat.html
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,217 @@
    <!DOCTYPE html>
    <html lang="en">

    <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Amazon IVS Broadcaster</title>
    <style>
    body {
    font-family: Arial, sans-serif;
    max-width: 800px;
    margin: 0 auto;
    padding: 20px;
    }

    .video-container {
    margin-bottom: 20px;
    }

    #local-video {
    width: 100%;
    background-color: #000;
    }

    .control-panel {
    display: flex;
    gap: 10px;
    margin-bottom: 20px;
    }

    button {
    padding: 10px 15px;
    cursor: pointer;
    }

    .streaming {
    background-color: #ff4d4d;
    }

    .status {
    padding: 10px;
    border-radius: 5px;
    margin-top: 10px;
    }

    .error {
    background-color: #ffcccc;
    }

    .success {
    background-color: #ccffcc;
    }
    </style>
    </head>

    <body>
    <h1>Amazon IVS Broadcaster</h1>

    <div class="video-container">
    <video id="local-video" autoplay muted playsinline></video>
    </div>

    <div class="control-panel">
    <button id="start-camera">Start Camera</button>
    <button id="start-stream" disabled>Start Streaming</button>
    <button id="stop-stream" disabled>Stop Streaming</button>
    </div>

    <div>
    <h3>Stream Settings</h3>
    <div>
    <label for="ingest-url">Ingest Server URL:</label>
    <input type="text" id="ingest-url" placeholder="rtmps://..." size="50">
    </div>
    <div>
    <label for="stream-key">Stream Key:</label>
    <input type="password" id="stream-key" placeholder="Your IVS stream key" size="50">
    </div>
    </div>

    <div id="status-message" class="status"></div>

    <!-- Amazon IVS Web Broadcast SDK -->
    <script src="https://web-broadcast.live-video.net/1.4.0/amazon-ivs-web-broadcast.js"></script>

    <script>
    const startCameraButton = document.getElementById('start-camera');
    const startStreamButton = document.getElementById('start-stream');
    const stopStreamButton = document.getElementById('stop-stream');
    const localVideo = document.getElementById('local-video');
    const ingestUrlInput = document.getElementById('ingest-url');
    const streamKeyInput = document.getElementById('stream-key');
    const statusMessage = document.getElementById('status-message');

    // Stream configuration
    const streamConfig = {
    maxResolution: {
    width: 1280,
    height: 720,
    },
    maxFramerate: 30,
    maxBitrate: 2500000,
    };

    let client;
    let streamSession;
    let cameraStream;

    // Check if the browser supports the IVS Web Broadcast SDK
    if (!IVSBroadcastClient.isSupported) {
    updateStatus("Browser is not supported for IVS broadcasting", true);
    }

    // Start camera and microphone
    startCameraButton.addEventListener('click', async () => {
    try {
    // Initialize the IVS Broadcast client
    client = IVSBroadcastClient.create({
    streamConfig: streamConfig,
    ingestEndpoint: "", // Will be set when starting the stream
    });

    // Get camera and microphone permissions
    cameraStream = await navigator.mediaDevices.getUserMedia({
    video: true,
    audio: true
    });

    // Display the camera preview
    localVideo.srcObject = cameraStream;

    // Add camera and microphone to the client
    const devices = await client.getDevices();

    // Add the video device
    await client.addVideoInputDevice(cameraStream, 'camera', { index: 0 });

    // Add the audio device
    await client.addAudioInputDevice(cameraStream, 'microphone');

    updateStatus("Camera started successfully. Ready to stream.", false);
    startStreamButton.disabled = false;
    startCameraButton.disabled = true;

    } catch (error) {
    updateStatus(`Error starting camera: ${error.message}`, true);
    }
    });

    // Start streaming
    startStreamButton.addEventListener('click', async () => {
    const ingestUrl = ingestUrlInput.value.trim();
    const streamKey = streamKeyInput.value.trim();

    if (!ingestUrl || !streamKey) {
    updateStatus("Please enter both ingest URL and stream key", true);
    return;
    }

    try {
    client.ingestEndpoint = ingestUrl;

    // Create a stream session
    streamSession = client.createStreamSession({
    ingestEndpoint: ingestUrl,
    streamKey: streamKey
    });

    // Listen for stream status events
    streamSession.addEventListener('error', (event) => {
    updateStatus(`Stream error: ${event.detail}`, true);
    });

    streamSession.addEventListener('connectionStateChange', (state) => {
    updateStatus(`Stream state: ${state}`, false);
    });

    // Start the stream
    await streamSession.start();

    updateStatus("Streaming started...", false);
    startStreamButton.disabled = true;
    stopStreamButton.disabled = false;
    startStreamButton.classList.add('streaming');

    } catch (error) {
    updateStatus(`Error starting stream: ${error.message}`, true);
    }
    });

    // Stop streaming
    stopStreamButton.addEventListener('click', async () => {
    try {
    if (streamSession) {
    await streamSession.stop();
    streamSession = null;
    }

    updateStatus("Stream stopped", false);
    startStreamButton.disabled = false;
    stopStreamButton.disabled = true;
    startStreamButton.classList.remove('streaming');

    } catch (error) {
    updateStatus(`Error stopping stream: ${error.message}`, true);
    }
    });

    // Update status message
    function updateStatus(message, isError) {
    statusMessage.textContent = message;
    statusMessage.className = isError ? 'status error' : 'status success';
    }
    </script>
    </body>

    </html>