### Install Boombox CLI Source: https://github.com/membraneframework/boombox/blob/master/README.md This command sequence shows how to download, make executable, and run the Boombox CLI. It requires wget and chmod utilities. The first execution will install Boombox in a default system directory, which can be customized using the MIX_INSTALL_DIR environment variable. ```bash wget https://raw.githubusercontent.com/membraneframework/boombox/v0.1.0/bin/boombox chmod u+x boombox ./boombox ``` -------------------------------- ### Initialize and Publish with WHIP Client (JavaScript) Source: https://github.com/membraneframework/boombox/blob/master/boombox_examples_data/whip.html This snippet initializes a WHIPClient and publishes a local media stream using WebRTC. It requires the 'whip-whep' library and DOM elements for UI interaction. The function handles user media acquisition, peer connection setup, and WHIP publishing, providing feedback on connection status. ```javascript import { WHIPClient } from 'https://cdn.jsdelivr.net/npm/whip-whep@1.2.0/whip.js' const button = document.getElementById("button"); const connStatus = document.getElementById("status"); const preview = document.getElementById("preview"); const url = document.getElementById("url"); const status = document.getElementById("status"); const token = document.getElementById("token"); const pcConfig = { iceServers: [ { urls: "stun:stun.l.google.com:19302" } ] }; const mediaConstraints = { video: true, audio: true }; const connect = async () => { connStatus.innerHTML = "Connecting..." const localStream = await navigator.mediaDevices.getUserMedia(mediaConstraints); preview.srcObject = localStream; const pc = new RTCPeerConnection(pcConfig); window.pc = pc; // for debugging purposes for (const track of localStream.getTracks()) { pc.addTransceiver(track, { 'direction': 'sendonly' }) } const whip = new WHIPClient(); await whip.publish(pc, url.value, token.value); connStatus.innerHTML = "Connected"; button.innerHTML = "Disconnect"; button.onclick = async () => { await whip.stop(); status.innerHTML = "Disconnected"; button.onclick = connect; } } button.onclick = connect; ``` -------------------------------- ### Install Boombox using pip Source: https://github.com/membraneframework/boombox/blob/master/python/README.md Installs the boomboxlib package from PyPI using pip. This is the standard method for installing Python packages. ```bash pip install boomboxlib ``` -------------------------------- ### Boombox CLI WebRTC via WHIP Source: https://context7.com/membraneframework/boombox/llms.txt Illustrates using the Boombox CLI to send a local file over WebRTC using the WHIP protocol. This example shows how to specify the output as a WHIP endpoint. ```bash # WebRTC via WHIP ./boombox -i file.mp4 -o --whip http://localhost:3721 --token mytoken ``` -------------------------------- ### Browser to Elixir WebSocket Connection and WebRTC Setup (JavaScript) Source: https://github.com/membraneframework/boombox/blob/master/boombox_examples_data/talk_to_llm.html Establishes a WebSocket connection from the browser to the Elixir backend and initializes a WebRTC PeerConnection. It handles sending SDP offers and ICE candidates to the server and receiving SDP answers and ICE candidates from it. This enables the browser to initiate audio streaming. ```javascript const pcConfig = { iceServers: [{"urls": "stun:stun.l.google.com:19302"}] }; const mediaConstraints = { video: false, audio: true }; const proto = window.location.protocol === "https:" ? "wss:" : "ws:"; const wsBrowserToElixir = new WebSocket(`${proto}//${window.location.hostname}:8829`); const connBrowserToElixirStatus = document.getElementById("status"); wsBrowserToElixir.onopen = (_) => start_connection_browser_to_elixir(wsBrowserToElixir); wsBrowserToElixir.onclose = (event) => { connBrowserToElixirStatus.innerHTML = "Disconnected"; console.log("WebSocket connection was terminated:", event); }; const start_connection_browser_to_elixir = async (ws) => { const localStream = await navigator.mediaDevices.getUserMedia(mediaConstraints); const pc = new RTCPeerConnection(pcConfig); pc.onicecandidate = (event) => { if (event.candidate === null) return; console.log("Sent ICE candidate:", event.candidate); ws.send(JSON.stringify({ type: "ice_candidate", data: event.candidate })); }; pc.onconnectionstatechange = () => { if (pc.connectionState == "connected") { const button = document.createElement("button"); button.innerHTML = "Disconnect"; button.onclick = () => { ws.close(); localStream.getTracks().forEach((track) => track.stop()); }; connBrowserToElixirStatus.innerHTML = "Connected "; connBrowserToElixirStatus.appendChild(button); } }; for (const track of localStream.getTracks()) { pc.addTrack(track, localStream); } ws.onmessage = async (event) => { const { type, data } = JSON.parse(event.data); switch (type) { case "sdp_answer": console.log("Received SDP answer:", data); await pc.setRemoteDescription(data); break; case "ice_candidate": console.log("Recieved ICE candidate:", data); await pc.addIceCandidate(data); } }; const offer = await pc.createOffer(); await pc.setLocalDescription(offer); console.log("Sent SDP offer:", offer); ws.send(JSON.stringify({ type: "sdp_offer", data: offer })); }; ``` -------------------------------- ### Install boomboxlib (Bash) Source: https://github.com/membraneframework/boombox/blob/master/python/examples/generate_hls_livestream/README.md Installs the necessary boomboxlib Python package using pip. Ensure you are in the correct directory relative to the boombox library source. ```bash pip install ../.. ``` -------------------------------- ### Elixir to Browser WebSocket Connection and WebRTC Setup (JavaScript) Source: https://github.com/membraneframework/boombox/blob/master/boombox_examples_data/talk_to_llm.html Establishes a WebSocket connection from the Elixir backend to the browser and initializes a WebRTC PeerConnection. It handles receiving SDP offers and ICE candidates from the browser and sending SDP answers and ICE candidates back. This enables the Elixir backend to stream audio to the browser. ```javascript const pcConfig = { iceServers: [{"urls": "stun:stun.l.google.com:19302"}] }; const audioPlayer = document.getElementById("audioPlayer"); const proto = window.location.protocol === "https:" ? "wss:" : "ws:"; const wsElixirToBrowser = new WebSocket(`${proto}//${window.location.hostname}:8830`); wsElixirToBrowser.onopen = () => start_connection_elixir_to_browser(wsElixirToBrowser); wsElixirToBrowser.onclose = (event) => console.log("WebSocket connection was terminated:", event); const start_connection_elixir_to_browser = async (ws) => { audioPlayer.srcObject = new MediaStream(); const pc = new RTCPeerConnection(pcConfig); pc.ontrack = (event) => audioPlayer.srcObject.addTrack(event.track); pc.onicecandidate = (event) => { if (event.candidate === null) return; console.log("Sent ICE candidate:", event.candidate); ws.send(JSON.stringify({ type: "ice_candidate", data: event.candidate })); }; ws.onmessage = async (event) => { const { type, data } = JSON.parse(event.data); switch (type) { case "sdp_offer": console.log("Received SDP offer:", data); await pc.setRemoteDescription(data); const answer = await pc.createAnswer(); await pc.setLocalDescription(answer); ws.send(JSON.stringify({ type: "sdp_answer", data: answer })); console.log("Sent SDP answer:", answer); break; case "ice_candidate": console.log("Recieved ICE candidate:", data); await pc.addIceCandidate(data); } }; }; ``` -------------------------------- ### Run Boombox HLS Demo (Bash) Source: https://github.com/membraneframework/boombox/blob/master/python/examples/generate_hls_livestream/README.md Executes the main Python script for the Boombox HLS livestream demo. This command starts the server that handles WebRTC stream reception and HLS conversion. ```bash python main.py ``` -------------------------------- ### Boombox CLI RTP Input with Encoding Parameters Source: https://context7.com/membraneframework/boombox/llms.txt Shows how to use the Boombox CLI to ingest an RTP stream and configure encoding parameters such as audio codec, specific configuration, and bitrate mode. This is useful for advanced streaming setups. ```bash # RTP input with encoding parameters ./boombox -i --rtp --port 50001 --audio-encoding AAC \ --audio-specific-config a13f --aac-bitrate-mode hbr \ -o index.m3u8 ``` -------------------------------- ### Writing Raw Media Data with Boombox Source: https://github.com/membraneframework/boombox/blob/master/python/docs/index.md This example shows how to use Boombox to accept raw audio and video packets and write them to a specified output endpoint. It utilizes a context manager for the Boombox instance and a packet generator to feed data into the stream. This pattern is suitable for scenarios where you are generating media data programmatically. ```python with Boombox( input=RawData(video=True, audio=True) output=any_output_endpoint ) as boombox: for packet in some_packet_generator(): boombox.write(packet) ``` -------------------------------- ### Boombox.async/2 (Elixir) Source: https://context7.com/membraneframework/boombox/llms.txt Provides an asynchronous version of the `run/2` function. It returns a Task, allowing for concurrent operations or starting streaming before the pipeline is fully set up. ```APIDOC ## POST /boombox/async ### Description Initiates a media processing pipeline asynchronously, returning a Task handle. This is useful for running multiple pipelines concurrently or for non-blocking operations. ### Method POST ### Endpoint /boombox/async ### Parameters #### Request Body - **input** (string | map | tuple) - Required - Specifies the media input source. - **output** (string | map | tuple) - Required - Specifies the media output destination. ### Request Example ```json { "input": "stream1.mp4", "output": {:webrtc, "ws://localhost:8830"} } ``` ### Response #### Success Response (200) - **task_id** (string) - An identifier for the asynchronous task. #### Response Example ```json { "task_id": "some_unique_task_id" } ``` ``` -------------------------------- ### Stream RTMP to HLS using Python Source: https://github.com/membraneframework/boombox/blob/master/README.md This Python code snippet shows how to achieve the same RTMP to HLS streaming functionality as the Elixir example, using the boombox Python package. It requires the boomboxlib package to be installed. ```python from boombox import boombox boombox(input="rtmp://localhost:5432", output="index.m3u8") ``` -------------------------------- ### Message Endpoint Communication with Boombox Source: https://context7.com/membraneframework/boombox/llms.txt Demonstrates using Boombox with a message endpoint for Elixir GenServer integration. It shows how to start Boombox to send packets as messages and how a GenServer can receive and process these messages, including handling the end of the stream. ```elixir defmodule MyMediaProcessor do use GenServer def start_link(_) do GenServer.start_link(__MODULE__, %{}) end def init(_) do # Start boombox with message output boombox_pid = Boombox.run( input: "video.mp4", output: {:message, video: :image, audio: false} ) {:ok, %{boombox: boombox_pid, frame_count: 0}} end def handle_info({:boombox_packet, pid, %Boombox.Packet{} = packet}, state) do # Process received packet IO.puts("Received frame #{state.frame_count}") {:noreply, %{state | frame_count: state.frame_count + 1}} end def handle_info({:boombox_finished, pid}, state) do IO.puts("Boombox finished after #{state.frame_count} frames") {:stop, :normal, state} end end # Message-based input boombox_pid = Boombox.run( input: {:message, video: :image, audio: false}, output: "output.mp4" ) # Send packets as messages packet = %Boombox.Packet{kind: :video, payload: image, pts: timestamp} send(boombox_pid, {:boombox_packet, packet}) # Signal end of stream send(boombox_pid, :boombox_close) ``` -------------------------------- ### Browser WebRTC Streaming with Boombox (JavaScript) Source: https://github.com/membraneframework/boombox/blob/master/boombox_examples_data/webrtc_from_browser.html This JavaScript code snippet sets up a WebRTC peer connection in the browser to stream media. It uses WebSockets for signaling to exchange SDP offers/answers and ICE candidates. Dependencies include the browser's WebRTC API and a WebSocket server. ```javascript const pcConfig = { 'iceServers': [{"urls": "stun:stun.l.google.com:19302"},] }; const mediaConstraints = { video: { width: 640, height: 480 }, audio: true }; const button = document.getElementById("button"); const connStatus = document.getElementById("status"); const preview = document.getElementById("preview"); const url = document.getElementById("url"); const connectRTC = async (ws) => { const localStream = await navigator.mediaDevices.getUserMedia(mediaConstraints); preview.srcObject = localStream; const pc = new RTCPeerConnection(pcConfig); window.pc = pc; // for debugging purposes pc.onicecandidate = event => { if (event.candidate === null) return; console.log("Sent ICE candidate:", event.candidate); ws.send(JSON.stringify({ type: "ice_candidate", data: event.candidate })); }; pc.onconnectionstatechange = () => { if (pc.connectionState == "connected") { button.innerHTML = "Disconnect"; button.onclick = () => { ws.close(); localStream.getTracks().forEach(track => track.stop()); button.onclick = connect; button.innerHTML = "Connect"; } connStatus.innerHTML = "Connected "; } } for (const track of localStream.getTracks()) { pc.addTrack(track, localStream); } ws.onmessage = async event => { const { type, data } = JSON.parse(event.data); switch (type) { case "sdp_answer": console.log("Received SDP answer:", data); await pc.setRemoteDescription(data); break; case "ice_candidate": console.log("Recieved ICE candidate:", data); await pc.addIceCandidate(data); break; } }; const offer = await pc.createOffer(); await pc.setLocalDescription(offer); console.log("Sent SDP offer:", offer) ws.send(JSON.stringify({ type: "sdp_offer", data: offer })); }; const connect = () => { connStatus.innerHTML = "Connecting..." const ws = new WebSocket(url.value); ws.onopen = _ => connectRTC(ws); ws.onclose = event => { connStatus.innerHTML = "Disconnected" button.onclick = connect; button.innerHTML = "Connect"; console.log("WebSocket connection was terminated:", event); } } button.onclick = connect; ``` -------------------------------- ### Elixir: Asynchronous Media Processing with Boombox.async/2 Source: https://context7.com/membraneframework/boombox/llms.txt Provides an asynchronous way to run media processing pipelines, returning a Task. This is useful for concurrent operations or when you need to start streaming before the pipeline fully completes. Supports running multiple instances concurrently. ```elixir # Start async RTMP receiver task = Boombox.async(input: "rtmp://localhost:5432", output: "index.m3u8") # Send stream with ffmpeg (runs concurrently) System.shell("ffmpeg -re -i input.mp4 -c copy -f flv rtmp://localhost:5432") # Wait for completion Task.await(task) # Run multiple boombox instances concurrently task1 = Boombox.async(input: "stream1.mp4", output: {:webrtc, "ws://localhost:8830"}) task2 = Boombox.async(input: "stream2.mp4", output: {:webrtc, "ws://localhost:8831"}) Task.await_many([task1, task2]) ``` -------------------------------- ### Stream RTMP to HLS using Elixir Source: https://github.com/membraneframework/boombox/blob/master/README.md This Elixir code snippet demonstrates how to receive an RTMP stream and output it as an HLS stream using the Boombox library. It requires the boombox library to be installed. ```elixir Boombox.run(input: "rtmp://localhost:5432", output: "index.m3u8") ``` -------------------------------- ### Play HLS Video with Boombox (JavaScript) Source: https://github.com/membraneframework/boombox/blob/master/boombox_examples_data/hls.html This snippet shows how to initialize and play an HLS video stream using the Boombox component. It requires an HTML element with the ID 'player' for the video and an input element with the ID 'source' to specify the HLS manifest URL. The Hls.js library is used to handle HLS playback. ```javascript function play() { var video = document.getElementById('player'); var hls = new Hls(); hls.loadSource(document.querySelector("#source").value); hls.attachMedia(video); } ``` ```javascript const source = document.querySelector("#source"); source.value = new URLSearchParams(window.location.search).get("src") || "output/index.m3u8"; play(); ``` -------------------------------- ### Connect to Boombox WebRTC Stream in Browser (JavaScript) Source: https://github.com/membraneframework/boombox/blob/master/boombox_examples_data/webrtc_to_browser.html This JavaScript code snippet sets up a WebRTC connection to a Boombox stream. It uses WebSockets for signaling and handles the peer connection lifecycle, including ICE candidate exchange and SDP offer/answer negotiation. It requires HTML elements with IDs 'button', 'status', 'url', and 'videoPlayer'. ```javascript const pcConfig = { 'iceServers': [{"urls": "stun:stun.l.google.com:19302"}] }; const button = document.getElementById("button"); const connStatus = document.getElementById("status"); const url = document.getElementById("url"); const videoPlayer = document.getElementById("videoPlayer"); const connectRTC = async (ws) => { videoPlayer.srcObject = new MediaStream(); const pc = new RTCPeerConnection(pcConfig); window.pc = pc; // for debugging purposes pc.ontrack = event => videoPlayer.srcObject.addTrack(event.track); videoPlayer.play(); pc.onicecandidate = event => { if (event.candidate === null) return; console.log("Sent ICE candidate:", event.candidate); ws.send(JSON.stringify({ type: "ice_candidate", data: event.candidate })); }; pc.onconnectionstatechange = () => { if (pc.connectionState == "connected") { connStatus.innerHTML = "Connected"; button.innerHTML = "Disconnect"; } } ws.onmessage = async event => { const { type, data } = JSON.parse(event.data); switch (type) { case "sdp_offer": console.log("Received SDP offer:", data); await pc.setRemoteDescription(data); const answer = await pc.createAnswer(); await pc.setLocalDescription(answer); ws.send(JSON.stringify({ type: "sdp_answer", data: answer })); console.log("Sent SDP answer:", answer) break; case "ice_candidate": console.log("Recieved ICE candidate:", data); await pc.addIceCandidate(data); } }; }; const connect = () => { const ws = new WebSocket(url.value); ws.onopen = () => connectRTC(ws); ws.onclose = event => { console.log("WebSocket connection was terminated:", event); connStatus.innerHTML = "Disconnected"; button.innerHTML = "Connect"; } } button.onclick = connect; ``` -------------------------------- ### WebRTC Stream Receiver Logic (JavaScript) Source: https://github.com/membraneframework/boombox/blob/master/python/examples/assets/receiver.html This JavaScript code implements the core logic for a WebRTC stream receiver. It handles WebSocket connections, RTCPeerConnection setup, SDP offer/answer exchange, ICE candidate gathering and transmission, and receiving media tracks. It relies on browser WebRTC APIs and WebSocket API. ```javascript const button = document.getElementById("button"); const connStatus = document.getElementById("status"); const urlInput = document.getElementById("url"); const videoPlayer = document.getElementById("videoPlayer"); const pcConfig = { 'iceServers': [{"urls": 'stun:stun.l.google.com:19302'}] }; let pc = null; let ws = null; const updateStatus = (message, stateClass) => { connStatus.innerText = message; connStatus.className = stateClass || ''; }; const connect = () => { button.disabled = true; urlInput.disabled = true; updateStatus("Connecting...", "status-connecting"); if (ws) { ws.onopen = ws.onclose = ws.onerror = null; ws.close(); } try { ws = new WebSocket(urlInput.value); } catch (e) { console.error("Failed to create WebSocket:", e); updateStatus("Error: Invalid WebSocket URL", "status-disconnected"); resetUI(); return; } ws.onopen = () => { console.log("WebSocket opened."); connectRTC(); }; ws.onclose = event => { console.log("WebSocket connection was terminated:", event); updateStatus("Disconnected", "status-disconnected"); if (pc) { pc.close(); pc = null; } videoPlayer.srcObject = null; resetUI(); }; ws.onerror = (error) => { console.error("WebSocket error:", error); updateStatus("Connection Error", "status-disconnected"); }; }; const connectRTC = () => { pc = new RTCPeerConnection(pcConfig); videoPlayer.srcObject = new MediaStream(); pc.ontrack = event => { console.log("Received track:", event.track); videoPlayer.srcObject.addTrack(event.track); }; pc.onicecandidate = event => { if (event.candidate === null) return; ws.send(JSON.stringify({ type: "ice_candidate", data: event.candidate })); }; pc.onconnectionstatechange = () => { console.log("PeerConnection state:", pc.connectionState); if (pc.connectionState == "connected") { updateStatus("Connected", "status-connected"); button.innerHTML = "Disconnect"; button.disabled = false; button.onclick = disconnect; } else if ([ "disconnected", "failed", "closed" ].includes(pc.connectionState)) { ws.close(); } }; ws.onmessage = async event => { try { const { type, data } = JSON.parse(event.data); switch (type) { case "sdp_offer": console.log("Received SDP offer"); await pc.setRemoteDescription(new RTCSessionDescription(data)); const answer = await pc.createAnswer(); await pc.setLocalDescription(answer); ws.send(JSON.stringify({ type: "sdp_answer", data: answer })); console.log("Sent SDP answer"); break; case "ice_candidate": console.log("Received ICE candidate"); await pc.addIceCandidate(new RTCIceCandidate(data)); break; } } catch(err) { console.error("Error processing message:", err); } }; }; const disconnect = () => { console.log("Disconnecting..."); button.disabled = true; if (ws) { ws.close(); } }; const resetUI = () => { button.disabled = false; urlInput.disabled = false; button.innerHTML = "Connect"; button.onclick = connect; }; button.onclick = connect; ``` -------------------------------- ### Boombox CLI Run Elixir Script Source: https://context7.com/membraneframework/boombox/llms.txt Demonstrates how to execute an Elixir script using the Boombox CLI. This allows for more complex media processing logic defined in Elixir to be run directly from the command line. ```bash # Run Elixir script ./boombox -s my_script.exs ``` -------------------------------- ### Boombox.Bin for Membrane Pipeline Integration Source: https://context7.com/membraneframework/boombox/llms.txt Explains how to use Boombox.Bin as a source or sink within a custom Membrane pipeline. This allows integrating Boombox's format handling capabilities with other Membrane elements for complex media processing workflows. ```elixir defmodule MyCustomPipeline do use Membrane.Pipeline @impl true def handle_init(_ctx, opts) do spec = [ # Use Boombox.Bin as input source child(:input_boombox, %Boombox.Bin{ input: opts[:input_file] }) |> via_out(:output, options: [kind: :video]) |> child(:video_processor, MyVideoFilter) |> via_in(:input, options: [kind: :video]) |> child(:output_boombox, %Boombox.Bin{ output: opts[:output_file] }), # Route audio directly get_child(:input_boombox) |> via_out(:output, options: [kind: :audio]) |> via_in(:input, options: [kind: :audio]) |> get_child(:output_boombox) ] {[spec: spec], %{}} end end # Start the pipeline {:ok, _supervisor, _pipeline} = Membrane.Pipeline.start_link(MyCustomPipeline, input_file: "input.mp4", output_file: {:webrtc, "ws://localhost:8830"} ) # Discard video, keep audio only defmodule AudioOnlyPipeline do use Membrane.Pipeline @impl true def handle_init(_ctx, opts) do spec = [ child(:input, %Boombox.Bin{input: opts[:input]}) |> via_out(:output, options: [kind: :audio]) |> via_in(:input, options: [kind: :audio]) |> child(:output, %Boombox.Bin{output: opts[:output]}), # Discard video get_child(:input) |> via_out(:output, options: [kind: :video]) |> child(Membrane.Fake.Sink) ] {[spec: spec], %{}} end end ``` -------------------------------- ### Read Packets On-Demand with Boombox Source: https://context7.com/membraneframework/boombox/llms.txt Demonstrates how to run Boombox to read packets from an input file and process them individually. It shows how to handle successful frame reads and the end of the stream, ensuring the reader is closed afterward. ```elixir reader = Boombox.run( input: "video.mp4", output: {:reader, video: :image, audio: false} ) case Boombox.read(reader) do {:ok, %Boombox.Packet{payload: image, pts: pts}} -> # Process frame IO.puts("Got frame at #{pts}") :finished -> IO.puts("Stream ended") end Boombox.close(reader) ``` -------------------------------- ### Python Endpoints: Configuring Inputs and Outputs Source: https://context7.com/membraneframework/boombox/llms.txt Illustrates how to configure various input and output endpoints using the Boombox Python library. This includes storage endpoints like MP4 and HLS, streaming protocols like WebRTC, WHIP, RTP, and raw data handling for Python integration. It also shows how to set transcoding policies. ```python from boombox import ( Boombox, RawData, MP4, HLS, WebRTC, WHIP, RTP, RTMP, RTSP, H264, H265, AAC, WAV, MP3, Ogg ) # Storage endpoints with options Boombox( input=H264("video.h264", framerate=(30, 1)), output=MP4("output.mp4") ) # HLS output with mode Boombox( input="input.mp4", output=HLS("output/index.m3u8", mode="live") ) # WebRTC with WebSocket signaling Boombox( input=WebRTC("ws://localhost:8829"), output=WebRTC("ws://localhost:8830") ) # WHIP endpoint Boombox( input=WHIP("http://localhost:8829", token="mytoken"), output=MP4("recording.mp4") ) # RTP with encoding configuration Boombox( input=RTP( port=50001, audio_encoding="OPUS", video_encoding="H264" ), output=HLS("output/index.m3u8") ) # RawData for Python integration Boombox( input=RawData( video=True, audio=True, is_live=True # For realtime input ), output=WebRTC("ws://localhost:8830") ) Boombox( input="input.mp4", output=RawData( video=True, audio=True, video_width=640, video_height=480, audio_rate=44100, audio_channels=2, audio_format="s16le", pace_control=True # Output at realtime pace ) ) # Transcoding policy Boombox( input="input.mp4", output=MP4("output.mp4", transcoding_policy="always") ) ``` -------------------------------- ### Boombox CLI Basic File Conversion Source: https://context7.com/membraneframework/boombox/llms.txt Shows the basic usage of the Boombox command-line interface for converting media files from one format to another. This is a straightforward way to perform common media transformations. ```bash # Install CLI wget https://raw.githubusercontent.com/membraneframework/boombox/v0.1.0/bin/boombox chmod u+x boombox # Basic file conversion ./boombox -i input.mp4 -o output.m3u8 ``` -------------------------------- ### Executing Elixir Scripts with Boombox CLI Source: https://github.com/membraneframework/boombox/blob/master/README.md Shows how to execute an Elixir script file (`.exs`) using the Boombox CLI. This allows for more complex operations by leveraging the full Elixir environment within the script. ```shell ./boombox -s script.exs ``` -------------------------------- ### Write Packets Manually with Boombox Source: https://context7.com/membraneframework/boombox/llms.txt Illustrates how to set up Boombox as a writer and manually generate and write packets to an output file. This is useful for creating media files programmatically. ```elixir writer = Boombox.run( input: {:writer, video: :image, audio: false}, output: "output.mp4" ) # Generate and write frames for i <- 1..100 do img = Image.new!(640, 480, color: :red) packet = %Boombox.Packet{ kind: :video, payload: img, pts: Membrane.Time.milliseconds(i * 33) } Boombox.write(writer, packet) end Boombox.close(writer) ``` -------------------------------- ### Boombox CLI Usage Source: https://github.com/membraneframework/boombox/blob/master/README.md This command demonstrates how to use the Boombox command-line interface to stream media. It takes input and output file paths or URLs as arguments. This is a convenient way to use Boombox without writing code. ```bash boombox -i "rtmp://localhost:5432" -o "index.m3u8" ``` -------------------------------- ### Python API: Basic File Conversion and Processing Source: https://context7.com/membraneframework/boombox/llms.txt Demonstrates basic file conversion from MP4 to M3U8 using the Boombox Python API. It also shows how to read media packets, process video frames by flipping them vertically, and write them to an output file. Audio reading with specific formats and generating video frames are also covered. The context manager for automatic cleanup is also illustrated. ```python from boombox import Boombox, VideoPacket, AudioPacket, RawData, MP4, HLS, WebRTC import numpy as np # Basic file conversion boombox = Boombox(input="input.mp4", output="output.m3u8") boombox.wait() # Process video frames - flip vertically boombox_in = Boombox( input="https://example.com/video.mp4", output=RawData(video=True, audio=True) ) bombox_out = Boombox( input=RawData(video=True, audio=True), output="output.mp4" ) for packet in boombox_in.read(): if isinstance(packet, VideoPacket): # payload is numpy array with shape (height, width, channels) packet.payload = np.flip(packet.payload, axis=0) boombox_out.write(packet) bombox_out.close(wait=True) # Read audio with specific format boombox = Boombox( input="audio.mp4", output=RawData( video=False, audio=True, audio_rate=16000, audio_channels=1, audio_format="f32le" ) ) for packet in boombox.read(): # packet.payload is numpy array of audio samples # packet.timestamp is in milliseconds # packet.sample_rate and packet.channels available process_audio(packet.payload) # Generate video frames boombox = Boombox( input=RawData(video=True, audio=False), output=MP4("output.mp4") ) for i in range(300): # 10 seconds at 30fps frame = np.zeros((480, 640, 3), dtype=np.uint8) frame[:, :, 0] = i % 256 # Animate red channel packet = VideoPacket( payload=frame, timestamp=i * 33 # milliseconds ) boombox.write(packet) bombox.close(wait=True) # Context manager for automatic cleanup with Boombox(input="input.mp4", output=RawData(video=True, audio=False)) as bb: for packet in bb.read(): process_frame(packet.payload) ``` -------------------------------- ### Elixir API to CLI Argument Mapping Source: https://github.com/membraneframework/boombox/blob/master/README.md Demonstrates how Elixir function calls to `Boombox.run/2` are translated into equivalent CLI commands. It covers the mapping of input/output options and various option types like strings, atoms, integers, and binaries. ```elixir Boombox.run(input: "file.mp4", output: {:whip, "http://localhost:3721", token: "token"}) Boombox.run( input: {:rtp, port: 50001, audio_encoding: :AAC, audio_specific_config: <<161, 63>>, aac_bitrate_mode: :hbr}, output: "index.m3u8" ) ``` ```shell ./boombox -i file.mp4 -o --whip http://localhost:3721 --token token ./boombox -i --rtp --port 50001 --audio-encoding AAC --audio-specific-config a13f --aac-bitrate-mode hbr -o index.m3u8 ``` -------------------------------- ### Core API - Boombox.run/2 (Elixir) Source: https://context7.com/membraneframework/boombox/llms.txt The main entry point for Boombox operations. It accepts input and output specifications to create media processing pipelines. This function blocks until processing completes for most endpoint types, with special behaviors for stream-based endpoints. ```APIDOC ## POST /boombox/run ### Description Processes media using specified input and output configurations. This is the primary function for creating media processing pipelines. ### Method POST ### Endpoint /boombox/run ### Parameters #### Request Body - **input** (string | map | tuple) - Required - Specifies the media input source. Can be a file path, URL, or a structured map/tuple for specific protocols (e.g., RTMP, WebRTC, RTP, SRT). - **output** (string | map | tuple) - Required - Specifies the media output destination. Can be a file path, URL, or a structured map/tuple for specific protocols. ### Request Example ```json { "input": "input.mp4", "output": "output/index.m3u8" } ``` ```json { "input": "rtmp://localhost:5432", "output": {:webrtc, "ws://0.0.0.0:1234"} } ``` ```json { "input": {:h264, "video.h264", {framerate: {30, 1}}}, "output": "output.ivf" } ``` ### Response #### Success Response (200) - **status** (string) - Indicates the success of the operation (e.g., "completed"). #### Response Example ```json { "status": "completed" } ``` ``` -------------------------------- ### Elixir Supported Formats: Input and Output Reference Source: https://context7.com/membraneframework/boombox/llms.txt Provides a comprehensive reference for all supported input and output formats within the Elixir ecosystem for the Boombox library. This includes file formats, HTTP sources, various streaming protocols like WebRTC, WHIP, RTMP, RTSP, HLS, SRT, and RTP configurations. Elixir-specific integration points and player output are also detailed. ```elixir # File formats (input & output) "file.mp4" # MP4 container "file.mp3" # MP3 audio "file.aac" # AAC audio "file.ogg" # Ogg container "file.wav" # WAV audio "file.ivf" # IVF container (VP8/VP9) {:h264, "file.h264", framerate: {30,1}} # Raw H264 with framerate {:h265, "file.h265", framerate: {30,1}} # Raw H265 with framerate # HTTP sources {:mp4, "https://example.com/video.mp4", transport: :http} # Streaming protocols {:webrtc, signaling} # WebRTC (signaling: URL or struct) {:whip, "http://url", token: "token"} # WHIP/WHEP "rtmp://host:port/app/key" # RTMP (input only) "rtsp://host:port/stream" # RTSP (input only) {:hls, "path/index.m3u8"} # HLS "srt://host:port" # SRT {:srt, "srt://host:port", stream_id: "id", password: "pass"} # RTP with configuration {:rtp, port: 5000, video_encoding: :H264, audio_encoding: :OPUS} # Elixir integration {:stream, video: :image, audio: :binary} # Stream endpoint {:reader, video: :image, audio: false} # Reader endpoint {:writer, audio: :binary, video: false} # Writer endpoint {:message, video: :image, audio: :binary} # Message endpoint # Player output :player # SDL2 media player ``` -------------------------------- ### Compose Two Video Streams Side-by-Side with Boombox Source: https://context7.com/membraneframework/boombox/llms.txt Shows how to read from two input video files, compose their frames horizontally using Vips, and write the combined stream to an output file. It handles stream synchronization by using the maximum PTS. ```elixir reader1 = Boombox.run(input: "video1.mp4", output: {:reader, video: :image, audio: false}) reader2 = Boombox.run(input: "video2.mp4", output: {:reader, video: :image, audio: false}) writer = Boombox.run(input: {:writer, video: :image, audio: false}, output: "combined.m3u8") Stream.repeatedly(fn -> case {Boombox.read(reader1), Boombox.read(reader2)} do {{:ok, p1}, {:ok, p2}} -> joined = Vix.Vips.Operation.join!(p1.payload, p2.payload, :VIPS_DIRECTION_HORIZONTAL) Boombox.write(writer, %Boombox.Packet{pts: max(p1.pts, p2.pts), payload: joined, kind: :video}) _ -> :eos end end) |> Enum.find(&(&1 == :eos)) Boombox.close(writer) ``` -------------------------------- ### Boombox CLI RTMP to HLS Conversion Source: https://context7.com/membraneframework/boombox/llms.txt Demonstrates how to use the Boombox CLI to ingest an RTMP stream and convert it into an HLS playlist. This is useful for live streaming scenarios. ```bash # RTMP to HLS ./boombox -i "rtmp://localhost:5432" -o "index.m3u8" ``` -------------------------------- ### Elixir: Play Media Locally with Boombox.play/2 Source: https://context7.com/membraneframework/boombox/llms.txt A convenience function for playing media directly on the local machine using the SDL2 player. It's a shortcut for `Boombox.run(input: input, output: :player)`. Supports local files, remote streams, and HLS. ```elixir # Play local MP4 file Boombox.play("path/to/video.mp4") # Play remote stream Boombox.play("rtmp://localhost:5432") # Play HLS stream Boombox.play("https://example.com/stream/index.m3u8") ``` -------------------------------- ### Elixir: Stream Media Packets with Elixir Enumerable Integration Source: https://context7.com/membraneframework/boombox/llms.txt Enables processing media as Elixir Streams, allowing integration with data processing pipelines and AI models. Packets contain raw audio/video data with timestamps. Supports reading video frames as images or audio as binary data, and generating video from streams. ```elixir # Read video frames as images from MP4 Boombox.run( input: "video.mp4", output: {:stream, video: :image, audio: false} ) |> Stream.each(fn %Boombox.Packet{payload: image, pts: timestamp} -> # Process each frame - image is a Vix.Vips.Image processed = Image.thumbnail!(image, 224) IO.puts("Frame at #{timestamp}") end) |> Stream.run() # Read audio as raw binary data Boombox.run( input: "audio.mp4", output: {:stream, video: false, audio: :binary, audio_rate: 16_000, audio_channels: 1, audio_format: :f32le} ) |> Stream.map(&Nx.from_binary(&1.payload, :f32)) |> Enum.each(&process_audio_chunk/1) # Generate video from Elixir stream and send via WebRTC Stream.iterate({0, 0}, fn {x, pts} -> {rem(x + 1, 640), pts + div(Membrane.Time.seconds(1), 30)} end) |> Stream.map(fn {x, pts} -> img = Image.new!(640, 480, color: :blue) %Boombox.Packet{kind: :video, payload: img, pts: pts} end) |> Boombox.run( input: {:stream, video: :image, audio: false}, output: {:webrtc, "ws://localhost:8830"} ) ``` -------------------------------- ### Read, Flip Video, and Save with Boombox Source: https://github.com/membraneframework/boombox/blob/master/python/README.md Demonstrates reading an MP4 file from a URL, flipping the video frames vertically, and saving the modified video to 'output.mp4'. It utilizes the Boombox library for media processing. ```python boombox1 = Boombox( input="https://raw.githubusercontent.com/membraneframework/static/gh-pages/samples/big-buck-bunny/bun33s.mp4", output=Array(video=True, audio=True), ) boombox2 = Boombox(input=Array(video=True, audio=True), output="output.mp4") for b in boombox1.read(): if isinstance(b, VideoPacket): b.payload = np.flip(b.payload, axis=0) boombox2.write(b) boombox2.close(wait=True) ``` -------------------------------- ### Reading Raw Media Data with Boombox Source: https://github.com/membraneframework/boombox/blob/master/python/docs/index.md This code illustrates how to configure Boombox to output raw audio and video packets. It sets up a Boombox instance with a generic input and a RawData output, then iterates through a generator to process each incoming packet. This is useful for real-time media manipulation. ```python boombox = Boombox( input=any_input_endpoint output=RawData(video=True, audio=True) ) for packet in boombox.read(): process_packet(packet) ``` -------------------------------- ### Elixir: Run Media Processing Pipelines with Boombox.run/2 Source: https://context7.com/membraneframework/boombox/llms.txt The core function for creating media processing pipelines. It accepts input and output specifications and blocks until processing is complete for most endpoint types. Supports file conversions, stream processing, and protocol bridging. ```elixir Boombox.run(input: "input.mp4", output: "output/index.m3u8") Boombox.run(input: "rtmp://localhost:5432", output: "index.m3u8") Boombox.run( input: "path/to/file.mp4", output: {:webrtc, "ws://0.0.0.0:1234"} ) Boombox.run( input: {:whip, "http://localhost:8829", token: "whip_it!"}, output: "recording.mp4" ) Boombox.run( input: {:h264, "video.h264", framerate: {30, 1}}, output: "output.ivf" ) Boombox.run( input: {:rtp, port: 50001, audio_encoding: :OPUS, video_encoding: :H264}, output: "index.m3u8" ) Boombox.run( input: {:srt, "srt://127.0.0.1:9710", stream_id: "my_stream", password: "secret"}, output: "output/index.m3u8" ) ``` -------------------------------- ### Boombox.play/2 (Elixir) Source: https://context7.com/membraneframework/boombox/llms.txt A convenience function to play media directly on the local machine using the SDL2 player. It's a shortcut for running a pipeline with the output set to the player. ```APIDOC ## POST /boombox/play ### Description Plays media content on the local machine using a built-in player. This is a simplified interface for immediate playback. ### Method POST ### Endpoint /boombox/play ### Parameters #### Request Body - **input** (string) - Required - The source of the media to play (e.g., local file path, URL). ### Request Example ```json { "input": "path/to/video.mp4" } ``` ### Response #### Success Response (200) - **status** (string) - Indicates that playback has started or is in progress. #### Response Example ```json { "status": "playing" } ``` ```