Skip to content

xbal023/server-stream-upload

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Media Embed Server (Go) — Upload • Stream/HLS • Iframe

A production-minded media server written in Go that lets you:

  • Upload audio, video, and images
  • Deliver audio/video via HLS (segmented playback, smooth buffering) and images via direct streaming
  • Embed playback on any website using a YouTube-style iframe
  • Manage uploads through a simple /admin page protected by an API key
  • Return a clean, professional JSON response containing iframe HTML, playback URLs, and metadata

Designed to stay responsive under load: HLS segments are cacheable, stream endpoints support Range requests, and ffmpeg transcoding is concurrency-limited.


Features

  • Media types
    • ✅ Audio → HLS (multi-bitrate AAC)
    • ✅ Video → HLS (H.264 + AAC)
    • ✅ Image → Stream (direct file)
  • Delivery
    • hls: /hls/{id}/master.m3u8
    • stream: /s/{id} (Range-enabled for audio/video/images)
    • embed: /embed/{id} (iframe-ready)
  • Admin
    • /admin requires API key (via ?apikey= or header X-API-Key)
    • Upload UI supports audio/video/image and shows iframe preview
  • API
    • Upload endpoint returns json{ iframe, track, filename, media, delivery, ... }
    • Public metadata endpoint for embed player
  • Security & Embed
    • CSP allows iframe embedding (frame-ancestors *)
    • CORS enabled for playback assets (HLS + stream)

Requirements

  • Go 1.20+ recommended
  • FFmpeg installed and available in PATH (or set FFMPEG_PATH)

Check FFmpeg:

ffmpeg -version

Quick Start

1) Create .env

PORT=3000
BASE_URL=<DOMAIN_SET>
DATA_DIR=./data
ADMIN_API_KEY=KEY_SECRET_API

MAX_UPLOAD_MB=1000
FFMPEG_PATH=ffmpeg
FFMPEG_WORKERS=6
HLS_SEGMENT_SECONDS=5

2) Install deps and run

go mod init media-embed
go get github.com/joho/godotenv
go run main.go

Open admin:

  • <DOMAIN_SET>/admin?apikey=KEY_SECRET_API

Folder Layout (Auto-created)

DATA_DIR/
  uploads/{id}/
    original.*        # uploaded file
    meta.json         # metadata
  hls/{id}/
    master.m3u8       # hls master playlist
    v064/             # audio variant
    v128/             # audio variant
    v192/             # audio variant
    seg_*.ts / *.aac  # segments

Admin Usage

  1. Go to: GET /admin?apikey=YOUR_ADMIN_API_KEY

  2. Upload a file (audio/video/image)

  3. Admin page will show:

  • JSON output
  • iframe preview
  • URLs you can use on other sites

API Reference

Authentication

Supply API key using either:

  • Header: X-API-Key: <YOUR_ADMIN_API_KEY>
  • Query: ?apikey=<YOUR_ADMIN_API_KEY> (admin page convenience)

1) Upload Media

POST /api/upload Auth: Required Body: multipart/form-data

Field:

  • file (required): audio/video/image

Example (curl):

curl -X POST "<DOMAIN_SET>/api/upload" \
  -H "X-API-Key: YOUR_ADMIN_API_KEY" \
  -F "file=@/path-to/video.mp4"

Success response (example):

{
  "ok": true,
  "id": "AbC123xYz890",
  "filename": "video.mp4",
  "media": "video",
  "delivery": "hls",
  "track": "AbC123xYz890",
  "embed_url": "<DOMAIN_SET>/embed/AbC123xYz890",
  "stream_url": "<DOMAIN_SET>/s/AbC123xYz890",
  "hls_master_url": "<DOMAIN_SET>/hls/AbC123xYz890/master.m3u8",
  "iframe": "<iframe src=\"<DOMAIN_SET>/embed/AbC123xYz890\" style=\"width:100%;height:360px;border:0\" allow=\"autoplay; fullscreen; picture-in-picture\" allowfullscreen loading=\"lazy\"></iframe>",
  "player_hints": {
    "embed": "/embed/{id}",
    "stream": "/s/{id}",
    "hls": "/hls/{id}/master.m3u8"
  }
}

Notes:

  • media is one of: audio | video | image
  • delivery is one of: hls | stream
    • audio/video → hls
    • image → stream

2) Public Metadata (for embed/player)

GET /api/media/{id} Auth: Not required

Example:

curl "<DOMAIN_SET>/api/media/AbC123xYz890"

Returns:

{
  "ok": true,
  "meta": {
    "id": "AbC123xYz890",
    "filename": "video.mp4",
    "media": "video",
    "delivery": "hls",
    "created_at": "2026-01-25T12:34:56Z",
    "size_bytes": 12345678,
    "orig_mime": "video/mp4",
    "stream_path": "/s/AbC123xYz890",
    "hls_master_url": "/hls/AbC123xYz890/master.m3u8",
    "embed_url": "<DOMAIN_SET>/embed/AbC123xYz890"
  }
}

3) Embed Player (YouTube-like)

GET /embed/{id} Designed to be used in an <iframe> on other websites.

Example:

<iframe src="https://your-domain.com/embed/AbC123xYz890" style="width:100%;height:360px;border:0" allow="autoplay; fullscreen; picture-in-picture" allowfullscreen loading="lazy"> </iframe>

The embed page:

  • Detects media type from /api/media/{id}

  • Renders:

    • <img> for images
    • <audio> for audio
    • <video> for video
  • Uses HLS when available, falls back to stream URL if needed


4) Direct Stream (Original File)

GET /s/{id}

  • Supports HTTP Range (great for progressive playback + seeking)
  • Used for images and as fallback for media

Example:

curl -I "<DOMAIN_SET>/s/AbC123xYz890"

5) HLS Assets

GET /hls/{id}/master.m3u8 And segments under:

  • /hls/{id}/...

HLS is the recommended delivery mode for audio/video at scale.


Performance Notes

  • HLS is cache-friendly Segments (.ts, .aac) can be cached for a long time, playlists (.m3u8) cached shorter.

  • Transcoding is CPU-heavy Use FFMPEG_WORKERS to cap concurrent ffmpeg jobs:

    • VPS 2 vCPU → 1–2
    • VPS 4 vCPU → 2–3
  • For large audiences Move /hls and /s to object storage + CDN:

    • Cloudflare R2 + CDN
    • S3 + CloudFront
    • Any CDN that supports caching and Range

Security Notes

  • Keep ADMIN_API_KEY long and secret.

  • For stricter embedding:

    • Replace frame-ancestors * with a whitelist, e.g. only your domains.
  • Consider adding:

    • Upload rate limiting
    • Virus scanning (optional)
    • Signed URLs (if media must be private)

Troubleshooting

“Embed works locally but not on other domains”

  • Ensure your reverse proxy/CDN isn’t adding X-Frame-Options: DENY or restrictive CSP.
  • Confirm the server responds with Content-Security-Policy containing frame-ancestors.

“Upload succeeds but playback fails”

  • Verify FFmpeg is installed and FFMPEG_PATH is correct.
  • Check server logs for ffmpeg ... failed.
  • Confirm HLS playlist exists: /hls/{id}/master.m3u8

“High CPU usage”

  • Lower FFMPEG_WORKERS
  • Increase segment duration (HLS_SEGMENT_SECONDS=6)
  • Consider async job queue + background workers for transcoding

Roadmap (Optional)

  • Async transcoding + job status endpoint (/api/jobs/{id})
  • Multi-bitrate video ABR (360p/720p/1080p)
  • Signed embed URLs & token-gated media
  • Post-processing: thumbnail extraction, waveform, metadata parsing

License

MIT (or choose your preferred license).

About

server streaming upload hls

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages