Merge branch 'main' of github.com:ffplayout/ffplayout-rs
This commit is contained in:
commit
d206967975
19
Cargo.lock
generated
19
Cargo.lock
generated
@ -143,7 +143,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ffplayout-rs"
|
||||
version = "0.1.0"
|
||||
version = "0.4.0"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"clap",
|
||||
@ -449,9 +449,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.119"
|
||||
version = "0.2.120"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1bf2e165bb3457c8e098ea76f3e3bc9db55f87aa90d52d0e6be741470916aaa4"
|
||||
checksum = "ad5c14e80759d0939d013e6ca49930e59fc53dd8e5009132f76240c179380c09"
|
||||
|
||||
[[package]]
|
||||
name = "linked-hash-map"
|
||||
@ -582,13 +582,12 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nom"
|
||||
version = "7.1.0"
|
||||
version = "7.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b1d11e1ef389c76fe5b81bcaf2ea32cf88b62bc494e19f493d0b30e7a930109"
|
||||
checksum = "a8903e5a29a317527874d0402f867152a3d21c908bb0b933e416c65e301d4c36"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"minimal-lexical",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -666,9 +665,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
|
||||
|
||||
[[package]]
|
||||
name = "openssl-src"
|
||||
version = "111.17.0+1.1.1m"
|
||||
version = "111.18.0+1.1.1n"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "05d6a336abd10814198f66e2a91ccd7336611f30334119ca8ce300536666fcf4"
|
||||
checksum = "7897a926e1e8d00219127dc020130eca4292e5ca666dd592480d72c3eca2ff6c"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
@ -956,9 +955,9 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.86"
|
||||
version = "1.0.89"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a65b3f4ffa0092e9887669db0eae07941f023991ab58ea44da8fe8e2d511c6b"
|
||||
checksum = "ea297be220d52398dcc07ce15a209fce436d361735ac1db700cab3b6cdfb9f54"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -1,8 +1,6 @@
|
||||
# cargo-features = ["strip"]
|
||||
|
||||
[package]
|
||||
name = "ffplayout-rs"
|
||||
version = "0.1.0"
|
||||
version = "0.4.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
@ -31,5 +29,6 @@ name = "ffplayout"
|
||||
path = "src/main.rs"
|
||||
|
||||
[profile.release]
|
||||
# strip = true
|
||||
opt-level = 3
|
||||
strip = true
|
||||
lto = true
|
||||
|
129
README.md
129
README.md
@ -5,10 +5,137 @@
|
||||
|
||||
Next generation 24/7 playout, based on [Rust](https://www.rust-lang.org/).
|
||||
|
||||
**At the moment this is only a playground and not ready for production!**
|
||||
**At the moment this project is in beta state, testing and feedback are welcome.**
|
||||
|
||||
**No feature requests please!**
|
||||
|
||||
If you search right now a working solution, try [ffplayout_engine](https://github.com/ffplayout/ffplayout_engine).
|
||||
|
||||
The main purpose of ffplayout is to provide a 24/7 broadcasting solution that plays a *json* playlist for every day, while keeping the current playlist editable.
|
||||
|
||||
**Check [ffplayout-frontend](https://github.com/ffplayout/ffplayout-frontend): web-based GUI for ffplayout**
|
||||
|
||||
**Features**
|
||||
-----
|
||||
|
||||
- have all values in a separate config file
|
||||
- dynamic playlist
|
||||
- replace missing playlist or clip with a dummy clip
|
||||
- playing clips from [watched folder](https://github.com/ffplayout/ffplayout_engine/wiki/Watch-Folder)
|
||||
- send emails with error message
|
||||
- overlay a logo
|
||||
- overlay text, controllable through [messenger](https://github.com/ffplayout/messenger) or [ffplayout-frontend](https://github.com/ffplayout/ffplayout-frontend) (needs ffmpeg with libzmq)
|
||||
- **EBU R128 loudness** normalization (single pass) (experimental)
|
||||
- loop playlist infinitely
|
||||
- trim and fade the last clip, to get full 24 hours
|
||||
- when playlist is not 24 hours long, loop filler clip until time is full
|
||||
- set custom day start, so you can have playlist for example: from 6am to 6am, instate of 0am to 12pm
|
||||
- normal system requirements and no special tools
|
||||
- no GPU power is needed
|
||||
- stream to server or play on desktop
|
||||
- logging to files, or colored output to console
|
||||
- add filters to input, if is necessary to match output stream:
|
||||
- **yadif** (deinterlacing)
|
||||
- **pad** (letterbox or pillarbox to fit aspect)
|
||||
- **fps** (change fps)
|
||||
- **scale** (fit target resolution)
|
||||
- **aevalsrc** (if video have no audio)
|
||||
- **apad** (add silence if audio duration is to short)
|
||||
- **tpad** (add black frames if video duration is to short)
|
||||
output):
|
||||
- **stream**
|
||||
- **desktop**
|
||||
|
||||
Requirements
|
||||
-----
|
||||
|
||||
- RAM and CPU depends on video resolution, minimum 4 threads and 3GB RAM for 720p are recommend
|
||||
|
||||
JSON Playlist Example
|
||||
-----
|
||||
|
||||
```json
|
||||
{
|
||||
"channel": "Test 1",
|
||||
"date": "2019-03-05",
|
||||
"program": [{
|
||||
"in": 0,
|
||||
"out": 647.68,
|
||||
"duration": 647.68,
|
||||
"source": "/Media/clip1.mp4"
|
||||
}, {
|
||||
"in": 0,
|
||||
"out": 149,
|
||||
"duration": 149,
|
||||
"source": "/Media/clip2.mp4"
|
||||
}, {
|
||||
"in": 0,
|
||||
"out": 114.72,
|
||||
"duration": 114.72,
|
||||
"source": "/Media/clip3.mp4",
|
||||
"category": "advertisement"
|
||||
}, {
|
||||
"in": 0,
|
||||
"out": 2531.36,
|
||||
"duration": 2531.36,
|
||||
"source": "/Media/clip4.mp4",
|
||||
"category": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**If you need a simple playlist generator check:** [playlist-generator](https://github.com/ffplayout/playlist-generator)
|
||||
|
||||
**Warning**
|
||||
-----
|
||||
|
||||
(Endless) streaming over multiple days will only work when config have **day_start** value and the **length** value is **24 hours**. If you need only some hours for every day, use a *cron* job, or something similar.
|
||||
|
||||
Remote source from URL
|
||||
-----
|
||||
|
||||
You can use sources from remote URL in that way:
|
||||
|
||||
```json
|
||||
{
|
||||
"in": 0,
|
||||
"out": 149,
|
||||
"duration": 149,
|
||||
"source": "https://example.org/big_buck_bunny.webm"
|
||||
}
|
||||
```
|
||||
|
||||
But be careful with it, better test it multiple times!
|
||||
|
||||
More informations in [Wiki](https://github.com/ffplayout/ffplayout_engine/wiki/Remote-URL-Source)
|
||||
|
||||
Installation
|
||||
-----
|
||||
|
||||
Copy the binary to `/usr/local/bin/`
|
||||
|
||||
Start with Arguments
|
||||
-----
|
||||
|
||||
ffplayout also allows the passing of parameters:
|
||||
|
||||
- `-c, --config <CONFIG>` file path to ffplayout.conf
|
||||
- `-f, --folder <FOLDER>` play folder content
|
||||
- `-h, --help` Print help information
|
||||
- `-i, --infinit` loop playlist infinitely
|
||||
- `-l, --log <LOG>` file path for logging
|
||||
- `-m, --play-mode <PLAY_MODE>` playing mode: folder, playlist
|
||||
- `-o, --output <OUTPUT>` set output mode: desktop, hls, stream
|
||||
- `-p, --playlist <PLAYLIST>` path from playlist
|
||||
- `-s, --start <START>` start time in 'hh:mm:ss', 'now' for start with first
|
||||
- `-t, --length <LENGTH>` set length in 'hh:mm:ss', 'none' for no length check
|
||||
- `-v, --volume <VOLUME>` set audio volume
|
||||
- `-V, --version` Print version information
|
||||
|
||||
|
||||
You can run the command like:
|
||||
|
||||
```SHELL
|
||||
./ffplayout.py -l none -p ~/playlist.json -o desktop
|
||||
```
|
||||
|
@ -28,6 +28,7 @@ logging:
|
||||
log_to_file: false
|
||||
backup_count: 7
|
||||
local_time: true
|
||||
timestamp: true
|
||||
log_path: "/var/log/ffplayout/"
|
||||
log_level: "DEBUG"
|
||||
ffmpeg_level: "error"
|
||||
|
14
assets/ffplayout_engine.service
Normal file
14
assets/ffplayout_engine.service
Normal file
@ -0,0 +1,14 @@
|
||||
[Unit]
|
||||
Description=python and ffmpeg based playout
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
ExecStart= /usr/local/bin/ffplayout
|
||||
ExecReload=/bin/kill -1 $MAINPID
|
||||
Restart=always
|
||||
RestartSec=1
|
||||
User=www-data
|
||||
Group=www-data
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
@ -44,6 +44,7 @@ pub struct Logging {
|
||||
pub log_to_file: bool,
|
||||
pub backup_count: usize,
|
||||
pub local_time: bool,
|
||||
pub timestamp: bool,
|
||||
pub log_path: String,
|
||||
pub log_level: String,
|
||||
pub ffmpeg_level: String,
|
||||
|
@ -103,13 +103,19 @@ async fn send_mail(msg: String) {
|
||||
pub fn init_logging(rt_handle: Handle) -> Vec<Box<dyn SharedLogger>> {
|
||||
let config = GlobalConfig::global();
|
||||
let app_config = config.logging.clone();
|
||||
let mut time_level = LevelFilter::Off;
|
||||
let mut app_logger: Vec<Box<dyn SharedLogger>> = vec![];
|
||||
|
||||
if app_config.timestamp {
|
||||
time_level = LevelFilter::Error;
|
||||
}
|
||||
|
||||
let log_config = simplelog::ConfigBuilder::new()
|
||||
.set_thread_level(LevelFilter::Off)
|
||||
.set_target_level(LevelFilter::Off)
|
||||
.set_level_padding(LevelPadding::Left)
|
||||
.set_time_to_local(app_config.local_time)
|
||||
.set_time_level(time_level)
|
||||
.clone();
|
||||
|
||||
if app_config.log_to_file {
|
||||
|
Loading…
Reference in New Issue
Block a user