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

 
 
 

Contributors

Languages