Decentralized Streaming
Powered by Walrus

Full-Stack Video Platform on Sui + Walrus Protocol
⏮ WALRUS HACKATHON DEMO ⏭
🎬

What is it?

A streaming platform where videos are stored permanently on Walrus and managed via Sui smart contracts

🔧

Tech Stack

Sui Move contracts + Walrus storage + Next.js frontend + Node.js transcoding

💡 The Challenge

How do you build a streaming platform that:

Why Walrus?

Traditional IPFS has slow retrieval and requires pinning services. Centralized storage (S3, GCS) defeats the purpose of Web3. Walrus Protocol provides decentralized storage with HTTP-based retrieval, erasure coding for redundancy, and native Sui integration.

🏗️ System Architecture

User Uploads Video
FFmpeg Transcoding
Walrus CLI Upload
Get Blob IDs
Register on Sui
Streaming Ready

Frontend (Next.js)

  • Sui Wallet Kit integration
  • Video.js player (HLS adaptive streaming)
  • Content library browsing
  • NFT membership cards (IPFS)

Backend (Node.js + TypeScript)

  • FFmpeg transcoding pipeline
  • Walrus CLI integration (bypass 10MB limit)
  • PostgreSQL (content metadata)
  • Sui SDK (@mysten/sui.js)

Blockchain (Sui Move)

  • MembershipNFT (dynamic display)
  • ContentRegistry (on-chain catalog)
  • Admin moderation (Pending → Active)
  • Streaming metrics tracking

Storage (Walrus + IPFS)

  • Walrus: Video files (all qualities)
  • IPFS/Pinata: NFT card images
  • HTTP aggregators for retrieval
  • 52-epoch storage windows

🦭 Walrus Integration Deep Dive

Challenge: Uploading Large Video Files

Problem: Walrus HTTP API has a 10MB upload limit. Video files are often 1GB+.

Solution: Use Walrus CLI directly via Node.js child process with retry logic.

// Walrus CLI Upload (walrus.service.ts)
async uploadFile(filePath: string, options) {
  const cmd = `walrus store \\
    --config ${this.configPath} \\
    --epochs ${options.epochs || 52} \\
    ${options.permanent ? '--permanent' : ''} \\
    "${filePath}"`;

  const result = await execAsync(cmd, {
    timeout: 600000,  // 10 minute timeout
    maxBuffer: 50 * 1024 * 1024
  });

  // Parse: "Blob ID: 1vwtsnn3dPnDqouEHcTfG5aV..."
  const blobId = this.parseBlobId(result.stdout);

  return {
    blobId,
    url: `${this.aggregatorUrl}/v1/${blobId}`,
    permanent: options.permanent
  };
}

Retrieval via HTTP Aggregator

// Generate streaming URL
const streamingUrl = `https://aggregator.walrus.atalma.io/v1/${blobId}`;

// Video.js HLS player consumes this directly
<video src={streamingUrl} controls />

⚡ Technical Challenges & Solutions

Challenge Solution Result
10MB HTTP upload limit Used Walrus CLI via child process ✅ Uploaded 5GB+ files successfully
Multi-quality transcoding FFmpeg pipeline (480p/720p/1080p/4K) ✅ Adaptive streaming working
CLI timeout on large files Increased maxBuffer + 10min timeout ✅ No more buffer overflow errors
Blob ID parsing from CLI output Regex extraction + error handling ✅ Reliable blob ID capture
Dynamic NFT images Sharp image processing + IPFS upload ✅ Personalized cards with member #
On-chain content registry Move smart contracts (3 packages) ✅ Deployed on Sui mainnet

Key Insight: CLI > HTTP API

For production streaming platforms, the Walrus CLI is essential. It handles large files reliably and provides better error messages than the HTTP API. We built a robust wrapper service with exponential backoff retry logic.

📜 Sui Smart Contracts

Three Move Packages (Deployed on Mainnet)

1. Membership Package

public struct MembershipNFT has key, store {
    id: UID,
    member_number: u64,        // Unique ID: #000042
    image_url: String,         // IPFS URL (active/expired card)
    expires_at: u64,           // Timestamp
    streams_used: u64,
    total_watch_time: u64,
}

// Dynamic NFT: image_url changes based on expiration
public fun get_display_url(nft: &MembershipNFT): String {
    if (clock::timestamp_ms() < nft.expires_at) {
        nft.active_card_url  // Green "ACTIVE" card
    } else {
        nft.expired_card_url // Red "EXPIRED" card
    }
}

2. Content Registry Package

public struct ContentItem has key, store {
    id: UID,
    blockchain_id: String,     // UUID reference
    uploader: address,
    title: String,
    walrus_blob_ids: vector<String>,  // [480p, 720p, 1080p, 4K]
    status: u8,                // 0=Pending, 1=Active, 2=Removed
    total_streams: u64,
    average_completion_rate: u64,
}

// Admin approval workflow
public entry fun approve_content(
    admin_cap: &AdminCap,
    registry: &mut ContentRegistry,
    content_id: String
) { /* ... */ }

🎬 Live Demo & Results

What Works Today

Deployed on Sui Mainnet
5GB+
Max File Size Tested
4K
Max Quality Support

Core Functionality

🔗 Transaction Hash (Mainnet Deployment)

F34RuAQy6y7HuFvBsmaJJanXQ6GsUHYA3yRKSPAMgf4F

View on SuiScan: suiscan.xyz/mainnet/tx/F34RuAQy...

WALRUS-POWERED STREAMING IS READY 🦭