Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ path = "src/whipinto.rs"
name = "whepfrom"
path = "src/whepfrom.rs"

[[bin]]
name = "livevod"
path = "src/livevod.rs"

[[bin]]
name = "net4mqtt"
path = "src/net4mqtt.rs"
Expand Down Expand Up @@ -106,11 +110,17 @@ net4mqtt = { path = "libs/net4mqtt" }
signal = { path = "libs/signal" }

storage = { path = "libs/storage" }
api = { path = "libs/api" }

clap = { workspace = true, features = ["derive"] }
tokio = { workspace = true, features = ["process"] }
tracing = { workspace = true }
serde = { workspace = true }
axum = { workspace = true }
axum-extra = { workspace = true }
serde_json = { workspace = true }
anyhow = { workspace = true }
opendal = "0.55.0"

toml = "1.0"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
Expand Down
21 changes: 13 additions & 8 deletions conf/live777.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,17 @@ urls = [
# Maximum duration in seconds before Live777 restarts a recording (0 disables auto-rotation)
# max_recording_seconds = 86400

# Async upload via Liveman presigned URLs
# [recorder.upload]
# enabled = false
# liveman_url = "http://127.0.0.1:8888"
# liveman_token = "live777"
# queue_path = "./recordings/upload_queue.jsonl"
# local_dir = "./recordings"
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤔

# presign_ttl_seconds = 300
# interval_ms = 2000
# concurrency = 2

# Storage backend configuration
[recorder.storage]
# Local filesystem (default)
Expand All @@ -52,14 +63,8 @@ root = "./storage"
#root = "/recordings"
#region = "us-east-1"

# Alibaba Cloud OSS
#type = "oss"
#bucket = "my-oss-bucket"
#root = "/recordings"
#region = "oss-cn-hangzhou"
#endpoint = "https://oss-cn-hangzhou.aliyuncs.com"
#access_key_id = "your-access-key"
#access_key_secret = "your-access-secret"
# Optional: custom endpoint for S3-compatible storage
#endpoint = "http://localhost:9000"

# [[ice_servers]]
# urls = [ "turn:turn.22333.fun", "turn:cn.22333.fun" ]
Expand Down
14 changes: 6 additions & 8 deletions conf/liveman.toml
Original file line number Diff line number Diff line change
Expand Up @@ -107,19 +107,17 @@ connect_timeout = 30
[recorder]

[recorder.storage]
# Storage type: "fs" for local filesystem; also supports "oss" (Alibaba Cloud OSS) and "s3"
# Local filesystem (default). Note: presign endpoint requires S3.
type = "fs"
# Root path for local filesystem
root = "./storage"

# Example: Alibaba Cloud OSS storage
# type = "oss"
# bucket = "my-oss-bucket"
# AWS S3 with explicit credentials
# type = "s3"
# bucket = "my-live777-bucket"
# root = "/recordings"
# region = "oss-cn-hangzhou"
# endpoint = "https://oss-cn-hangzhou.aliyuncs.com"
# region = "us-east-1"
# access_key_id = "your-access-key"
# access_key_secret = "your-access-secret"
# secret_access_key = "your-access-secret"

# Liveman auto recording configuration (manager-driven)
[auto_record]
Expand Down
40 changes: 40 additions & 0 deletions conf/livevod.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
[http]
# Http Server Listen Address
# listen = "0.0.0.0:8899"

[log]
# Env: `LOG_LEVEL`
# Default: info
# Values: off, error, warn, info, debug, trace
# level = "info"

# Playback index path (JSONL or JSON array)
index_path = "./recordings/index.json"

# Storage backend configuration
[storage]
# Local filesystem (default)
type = "fs"
root = "./recordings"

# AWS S3 with explicit credentials
#type = "s3"
#bucket = "my-live777-bucket"
#root = "/recordings"
#region = "us-east-1"
#access_key_id = "AKIAIOSFODNN7EXAMPLE"
#secret_access_key = "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"

# AWS S3 with IAM role (recommended for EC2/ECS)
#type = "s3"
#bucket = "my-live777-bucket"
#root = "/recordings"
#region = "us-east-1"

# Optional: custom endpoint for S3-compatible storage
#endpoint = "http://localhost:9000"

[playback]
# Whether to use signed redirects for non-MPD objects
# signed_redirect = false
# signed_ttl_seconds = 60
7 changes: 6 additions & 1 deletion docs/guide/liveman.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,12 @@ connect_timeout = 30

## Recording Index and Storage

The recording system stores the index (date-based manifest location) in the database while keeping the actual media files in storage (filesystem, S3, OSS, etc.).
The recording system stores the index (date-based manifest location) in the database while keeping the actual media files in the configured storage backend (filesystem or S3).

Liveman also exposes a storage API used by Liveion's async upload queue (S3 only):

- `POST /api/storage/presign` with `{ "method": "PUT", "path": "object", "ttl_seconds": 300 }` — generates a presigned URL; requires S3
- `GET /api/storage/ping` — checks storage availability

### Recording Index Schema

Expand Down
39 changes: 39 additions & 0 deletions docs/guide/livevod.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# LiveVOD

LiveVOD is a lightweight playback service that depends on a local `index.json` (JSONL) and a storage backend (filesystem or S3).

## Configuration

```toml
[http]
# listen = "0.0.0.0:8899"

# Playback index path (JSONL or JSON array)
index_path = "./storage/index.json"

# Local filesystem storage (default)
[storage]
type = "fs"
root = "./storage"

# AWS S3 storage
# [storage]
# type = "s3"
# bucket = "my-live777-bucket"
# root = "/recordings"
# region = "us-east-1"

[playback]
# signed_redirect = false # S3 only: redirect media segments via presigned URLs
# signed_ttl_seconds = 60
```

## APIs

- List streams: `GET /api/playback`
- List records for stream: `GET /api/playback/{stream}`
- Find record by timestamp: `GET /api/playback/{stream}/at?ts=...`
- `ts` accepts seconds, milliseconds, or microseconds.
- Proxy object: `GET /api/record/object/{path}`

When `playback.signed_redirect = true`, non-MPD objects are redirected using presigned URLs. This requires S3 storage; it has no effect with the filesystem backend.
Loading
Loading