Skip to content

Latest commit

Β 

History

16 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

LOVE

Live Onchain Video Environment


What is LOVE?

LOVE is a decentralized live streaming platform built on Celestia's data availability layer. It captures video and audio from your webcam/microphone, encodes them using H.264 video compression, multiplexes them into 2MB data chunks (~8 seconds of A/V), and submits them as blobs to the Celestia blockchain. Viewers can then fetch these blobs and play back the stream in real-time with synchronized audio and video.

Features

  • Live Streaming: Real-time video capture from webcam with configurable resolution and framerate
  • H.264 Video Compression: Efficient video encoding using ffmpeg for optimal streaming
  • Audio Support: Synchronized audio capture from microphone (16-bit PCM, configurable sample rate)
  • Local Preview: Optional local preview window for monitoring your stream
  • On-chain Storage: Stream data is stored as Celestia blobs with automatic gas estimation
  • A/V Sync: Timestamp-based synchronization ensures proper audio/video playback
  • Background Prefetching: Viewer fetches blobs in background for smooth playback
  • Decentralized: No central server - streams go directly to the blockchain
  • Censorship Resistant: Once on-chain, streams cannot be removed
  • Pluggable Codec: Interface-based design allows swapping encoding implementations

Quick Start

Prerequisites

  1. Go 1.21+

  2. ffmpeg (required for H.264 encoding/decoding)

    # macOS
    brew install ffmpeg
    
    # Ubuntu/Debian
    apt install ffmpeg
  3. OpenCV 4.x with GoCV bindings

    # macOS
    brew install opencv
    
    # Ubuntu/Debian
    apt install libopencv-dev
  4. Audio libraries (Linux only)

    # Ubuntu/Debian (ALSA)
    apt install libasound2-dev
  5. Celestia light node running locally (or remote node access)

  6. Auth token for Celestia node

Installation

git clone https://github.com/vgonkivs/love.git
cd love
make build

Get Celestia Auth Token

celestia light auth admin --p2p.network <network>

Usage

Using Make (Recommended)

# Stream with local preview
make stream token=<auth_token>

# Stream with custom settings
make stream token=<auth_token> fps=15 width=640 height=480

# View a stream
make view token=<auth_token> namespace=<hex> start_height=<height>

# Show help
make help

Using Binary Directly

# Basic streaming
./love stream -token <auth_token>

# Custom settings
./love stream -width 1920 -height 1080 -fps 30 -bitrate 4M -samplerate 48000 -token <auth_token>

# View a stream
./love view -namespace <namespace_hex> -height <start_height> -token <auth_token>

Press ESC to stop streaming or exit viewer.

Make Variables

Variable Default Description
token Celestia auth token (required)
node http://localhost:26658 Celestia node URL
camera 0 Camera device ID
width 1280 Video width (pixels)
height 720 Video height (pixels)
fps 30 Frames per second
namespace Stream namespace hex (required for view)
start_height Start block height (required for view)

Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                              STREAMING                                       β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                              β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚   β”‚                         Capturer                                      β”‚  β”‚
β”‚   β”‚  1. Send entrypoint blob (metadata)                                  β”‚  β”‚
β”‚   β”‚  2. Initialize devices:                                              β”‚  β”‚
β”‚   β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                                                        β”‚  β”‚
β”‚   β”‚  β”‚  Webcam  │──┐                                                     β”‚  β”‚
β”‚   β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”              β”‚  β”‚
β”‚   β”‚                β”œβ”€β”€β”€β–Άβ”‚   Encoder    │───▢│ Preview     β”‚              β”‚  β”‚
β”‚   β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚    β”‚  (H.264)     β”‚    β”‚ Window      β”‚              β”‚  β”‚
β”‚   β”‚  β”‚   Mic    β”‚β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜              β”‚  β”‚
β”‚   β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜              β”‚                                         β”‚  β”‚
β”‚   β”‚                            β–Ό                                         β”‚  β”‚
β”‚   β”‚                      2MB Blobs                                       β”‚  β”‚
β”‚   β”‚                      3. Send stream end blob                         β”‚  β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β”‚                                          β”‚                                   β”‚
β”‚                                          β–Ό                                   β”‚
β”‚                              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                        β”‚
β”‚                              β”‚      Streamer        β”‚                        β”‚
β”‚                              β”‚  - Random namespace  β”‚                        β”‚
β”‚                              β”‚  - Submit to Celestiaβ”‚                        β”‚
β”‚                              β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                        β”‚
β”‚                                         β”‚                                    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                          β”‚
                                          β–Ό
                               β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                               β”‚   Celestia Network   β”‚
                               β”‚                      β”‚
                               β”‚   Blobs stored in    β”‚
                               β”‚   namespace at       β”‚
                               β”‚   sequential heights β”‚
                               β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                          β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                              VIEWING    β”‚                                    β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                         β–Ό                                    β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚   β”‚                          Viewer                                       β”‚  β”‚
β”‚   β”‚                                                                       β”‚  β”‚
β”‚   β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚  β”‚
β”‚   β”‚  β”‚ Background      │───▢│   Decoder    │───▢│  Display (GoCV)    β”‚   β”‚  β”‚
β”‚   β”‚  β”‚ Blob Fetcher    β”‚    β”‚  (H.264)     β”‚    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚  β”‚
β”‚   β”‚  β”‚ (prefetching)   β”‚    β”‚              β”‚    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚  β”‚
β”‚   β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚              │───▢│  Audio Player      β”‚   β”‚  β”‚
β”‚   β”‚                         β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚  (malgo)           β”‚   β”‚  β”‚
β”‚   β”‚                                             β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚  β”‚
β”‚   β”‚  A/V Sync: Video paced by timestamps, audio plays at sample rate    β”‚  β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β”‚                                                                              β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Codec Interface

LOVE uses a pluggable codec architecture. The current implementation is H264Encoder/Decoder using ffmpeg, but the interface allows for alternative implementations:

// Encoder encodes video and audio frames for streaming
type Encoder interface {
    EncodeVideo(frame gocv.Mat, timestamp time.Duration, sequence uint32) ([]byte, error)
    EncodeAudio(samples []byte, timestamp time.Duration, sequence uint32) ([]byte, error)
    CreateEntrypoint(sampleRate int, channels int, fps int) []byte
    CreateStreamEnd(totalDuration time.Duration, totalFrames uint32) []byte
}

// Decoder decodes multiplexed video and audio frames
type Decoder interface {
    Decode(data []byte) (*DecodedFrame, int)
    ParseEntrypoint(data []byte) (sampleRate int, channels int, fps int, valid bool)
}

Data Format

Frame Header (20 bytes)

Each video/audio frame is prefixed with a header:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Marker   β”‚   Size    β”‚   Timestamp     β”‚   Sequence   β”‚
β”‚  4 bytes  β”‚  4 bytes  β”‚    8 bytes      β”‚   4 bytes    β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ "H264" or β”‚  Payload  β”‚  Nanoseconds    β”‚   Frame      β”‚
β”‚ "AUDF"    β”‚  length   β”‚  since start    β”‚   number     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
  • H264: H.264 encoded video frame (may contain multiple NAL units: SPS, PPS, IDR, P-frames)
  • AUDF: Audio frame (16-bit PCM samples)

Blob Structure

Frames are accumulated into 2MB blobs (~8 seconds of A/V at 2Mbps video + 128kbps audio):

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    2MB Blob                             β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ [Header][H.264 Data][Header][PCM Data][Header][H.264]...β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Entrypoint Blob

The Capturer sends an entrypoint blob first (before camera initialization) with stream metadata:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Marker   β”‚ Sample Rate β”‚ Channels β”‚   FPS   β”‚ Codec β”‚ Width β”‚ Height β”‚
β”‚  4 bytes  β”‚   4 bytes   β”‚  1 byte  β”‚ 1 byte  β”‚1 byte β”‚2 bytesβ”‚2 bytes β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  "ENTR"   β”‚   44100     β”‚    1     β”‚   30    β”‚   1   β”‚ 1280  β”‚  720   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Codec: 0 = JPEG (legacy), 1 = H.264

Stream End Blob

When the stream ends gracefully (ESC or Ctrl+C), the Capturer sends a stream end notification:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Marker   β”‚  Total Duration     β”‚ Total Frames β”‚
β”‚  4 bytes  β”‚     8 bytes         β”‚   4 bytes    β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  "ENDS"   β”‚  Nanoseconds        β”‚   Count      β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

This allows viewers to distinguish between "stream ended gracefully" vs "stream stopped unexpectedly".

Command Reference

Stream Options

Option Default Description
-camera 0 Camera device ID
-width 1280 Video width (pixels)
-height 720 Video height (pixels)
-fps 30 Frames per second
-bitrate 2M H.264 bitrate (e.g., 2M, 4M)
-samplerate 44100 Audio sample rate (Hz)
-node http://localhost:26658 Celestia node URL
-token Auth token (required)

View Options

Option Default Description
-namespace Stream namespace hex (required)
-height Start block height (required)
-node http://localhost:26658 Celestia node URL
-token Auth token (required)

How It Works

Streaming

  1. Entrypoint: Capturer sends entrypoint blob with stream metadata (sample rate, channels, fps, dimensions, codec)
  2. Initialize: Capturer opens webcam (GoCV) and microphone (malgo)
  3. Preview: Frames are displayed in local preview window (optional)
  4. Encode: Video frames are H.264 encoded via ffmpeg (SPS/PPS/IDR combined), audio is 16-bit PCM
  5. Multiplex: Frames are tagged with H264/AUDF markers and timestamps
  6. Chunk: Data is accumulated into 2MB buffers inside Capturer (~8 seconds of A/V)
  7. Submit: Blobs are submitted to Celestia via Streamer with automatic gas estimation
  8. Stream End: When stopping gracefully, Capturer sends stream end blob with total duration and frame count

Viewing

  1. Connect: Viewer connects to Celestia node
  2. Find Entrypoint: Locate the ENTR blob with stream parameters and codec type
  3. Create Decoder: Initialize H.264 decoder based on codec identifier
  4. Background Fetch: Goroutine prefetches blobs at sequential block heights into a buffered channel
  5. Decode: Parse frame headers, decode H.264 video via ffmpeg, extract PCM audio
  6. A/V Sync: Video is paced by timestamps, audio plays at native sample rate through malgo
  7. Display: Show video in window, play audio through speakers
  8. SPS/PPS Caching: Decoder caches parameter sets for mid-stream joining

Package Structure

love/
β”œβ”€β”€ main.go              # CLI entry point
β”œβ”€β”€ Makefile             # Build and run commands
β”œβ”€β”€ cmd/
β”‚   └── chaintest/       # H.264 encode/decode chain test app
β”‚       └── main.go
β”œβ”€β”€ lib/
β”‚   β”œβ”€β”€ capture/         # Video + audio capture with embedded encoder
β”‚   β”‚   β”œβ”€β”€ capture.go   # Capturer implementation
β”‚   β”‚   └── config.go    # Capture configuration
β”‚   β”œβ”€β”€ codec/           # Encoding/decoding interfaces and implementations
β”‚   β”‚   β”œβ”€β”€ interface.go # Encoder/Decoder interfaces
β”‚   β”‚   β”œβ”€β”€ jpeg.go      # JPEGCodec implementation (legacy)
β”‚   β”‚   β”œβ”€β”€ h264_encoder.go # H.264 encoder using ffmpeg
β”‚   β”‚   β”œβ”€β”€ h264_decoder.go # H.264 decoder using ffmpeg
β”‚   β”‚   β”œβ”€β”€ codec.go     # Shared constants and helpers
β”‚   β”‚   └── decoder.go   # Frame decoding utilities
β”‚   β”œβ”€β”€ streamer/        # Celestia blob submission
β”‚   β”‚   β”œβ”€β”€ streamer.go  # Streamer implementation
β”‚   β”‚   └── config.go    # Streamer configuration
β”‚   └── viewer/          # Blob fetching + playback with embedded decoder
β”‚       β”œβ”€β”€ viewer.go    # Viewer implementation (background fetcher + A/V sync)
β”‚       └── config.go    # Viewer configuration

Troubleshooting

Video not displaying

  • Ensure ffmpeg is installed: ffmpeg -version
  • Check if OpenCV/GoCV is properly installed

Audio not working

  • Linux: Install ALSA dev libraries: apt install libasound2-dev
  • Check microphone permissions

"non-existing PPS referenced" errors

  • This happens when joining mid-stream before a keyframe
  • Wait for the next keyframe or restart from an earlier height

A/V out of sync

  • Ensure you're using a fresh recording (old recordings may have sync issues)
  • The viewer uses timestamp-based sync - video paced by timestamps, audio at native rate

License

MIT


Go live with LOVE

About

Go live with LOVE

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages