fix channel delete/create, copy assets to storage, start with vtt support
This commit is contained in:
parent
da970aa4ff
commit
93e753129e
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@ -48,12 +48,13 @@
|
|||||||
},
|
},
|
||||||
"cSpell.words": [
|
"cSpell.words": [
|
||||||
"actix",
|
"actix",
|
||||||
|
"canonicalize",
|
||||||
"ffpengine",
|
"ffpengine",
|
||||||
"flexi",
|
"flexi",
|
||||||
"lettre",
|
"lettre",
|
||||||
"libc",
|
"libc",
|
||||||
"nuxt",
|
|
||||||
"neli",
|
"neli",
|
||||||
|
"nuxt",
|
||||||
"paris",
|
"paris",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
"rsplit",
|
"rsplit",
|
||||||
|
@ -120,6 +120,9 @@ If you are in playlist mode and move backwards or forwards in time, the time shi
|
|||||||
|
|
||||||
(Endless) streaming over multiple days will only work if config has a **day_start** value and the **length** value is **24 hours**. If you only need a few hours for each day, use a *cron* job or something similar.
|
(Endless) streaming over multiple days will only work if config has a **day_start** value and the **length** value is **24 hours**. If you only need a few hours for each day, use a *cron* job or something similar.
|
||||||
|
|
||||||
|
## Note
|
||||||
|
This project includes the DejaVu font, which are licensed under the [Bitstream Vera Fonts License](/assets/FONT_LICENSE.txt).
|
||||||
|
|
||||||
-----
|
-----
|
||||||
|
|
||||||
## Sponsoring
|
## Sponsoring
|
||||||
|
BIN
assets/DejaVuSans.ttf
Normal file
BIN
assets/DejaVuSans.ttf
Normal file
Binary file not shown.
187
assets/FONT_LICENSE.txt
Normal file
187
assets/FONT_LICENSE.txt
Normal file
@ -0,0 +1,187 @@
|
|||||||
|
Fonts are (c) Bitstream (see below). DejaVu changes are in public domain.
|
||||||
|
Glyphs imported from Arev fonts are (c) Tavmjong Bah (see below)
|
||||||
|
|
||||||
|
|
||||||
|
Bitstream Vera Fonts Copyright
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera is
|
||||||
|
a trademark of Bitstream, Inc.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of the fonts accompanying this license ("Fonts") and associated
|
||||||
|
documentation files (the "Font Software"), to reproduce and distribute the
|
||||||
|
Font Software, including without limitation the rights to use, copy, merge,
|
||||||
|
publish, distribute, and/or sell copies of the Font Software, and to permit
|
||||||
|
persons to whom the Font Software is furnished to do so, subject to the
|
||||||
|
following conditions:
|
||||||
|
|
||||||
|
The above copyright and trademark notices and this permission notice shall
|
||||||
|
be included in all copies of one or more of the Font Software typefaces.
|
||||||
|
|
||||||
|
The Font Software may be modified, altered, or added to, and in particular
|
||||||
|
the designs of glyphs or characters in the Fonts may be modified and
|
||||||
|
additional glyphs or characters may be added to the Fonts, only if the fonts
|
||||||
|
are renamed to names not containing either the words "Bitstream" or the word
|
||||||
|
"Vera".
|
||||||
|
|
||||||
|
This License becomes null and void to the extent applicable to Fonts or Font
|
||||||
|
Software that has been modified and is distributed under the "Bitstream
|
||||||
|
Vera" names.
|
||||||
|
|
||||||
|
The Font Software may be sold as part of a larger software package but no
|
||||||
|
copy of one or more of the Font Software typefaces may be sold by itself.
|
||||||
|
|
||||||
|
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT,
|
||||||
|
TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME
|
||||||
|
FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING
|
||||||
|
ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES,
|
||||||
|
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
|
||||||
|
THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE
|
||||||
|
FONT SOFTWARE.
|
||||||
|
|
||||||
|
Except as contained in this notice, the names of Gnome, the Gnome
|
||||||
|
Foundation, and Bitstream Inc., shall not be used in advertising or
|
||||||
|
otherwise to promote the sale, use or other dealings in this Font Software
|
||||||
|
without prior written authorization from the Gnome Foundation or Bitstream
|
||||||
|
Inc., respectively. For further information, contact: fonts at gnome dot
|
||||||
|
org.
|
||||||
|
|
||||||
|
Arev Fonts Copyright
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
Copyright (c) 2006 by Tavmjong Bah. All Rights Reserved.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of the fonts accompanying this license ("Fonts") and
|
||||||
|
associated documentation files (the "Font Software"), to reproduce
|
||||||
|
and distribute the modifications to the Bitstream Vera Font Software,
|
||||||
|
including without limitation the rights to use, copy, merge, publish,
|
||||||
|
distribute, and/or sell copies of the Font Software, and to permit
|
||||||
|
persons to whom the Font Software is furnished to do so, subject to
|
||||||
|
the following conditions:
|
||||||
|
|
||||||
|
The above copyright and trademark notices and this permission notice
|
||||||
|
shall be included in all copies of one or more of the Font Software
|
||||||
|
typefaces.
|
||||||
|
|
||||||
|
The Font Software may be modified, altered, or added to, and in
|
||||||
|
particular the designs of glyphs or characters in the Fonts may be
|
||||||
|
modified and additional glyphs or characters may be added to the
|
||||||
|
Fonts, only if the fonts are renamed to names not containing either
|
||||||
|
the words "Tavmjong Bah" or the word "Arev".
|
||||||
|
|
||||||
|
This License becomes null and void to the extent applicable to Fonts
|
||||||
|
or Font Software that has been modified and is distributed under the
|
||||||
|
"Tavmjong Bah Arev" names.
|
||||||
|
|
||||||
|
The Font Software may be sold as part of a larger software package but
|
||||||
|
no copy of one or more of the Font Software typefaces may be sold by
|
||||||
|
itself.
|
||||||
|
|
||||||
|
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||||
|
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL
|
||||||
|
TAVMJONG BAH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||||
|
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||||
|
OTHER DEALINGS IN THE FONT SOFTWARE.
|
||||||
|
|
||||||
|
Except as contained in this notice, the name of Tavmjong Bah shall not
|
||||||
|
be used in advertising or otherwise to promote the sale, use or other
|
||||||
|
dealings in this Font Software without prior written authorization
|
||||||
|
from Tavmjong Bah. For further information, contact: tavmjong @ free
|
||||||
|
. fr.
|
||||||
|
|
||||||
|
TeX Gyre DJV Math
|
||||||
|
-----------------
|
||||||
|
Fonts are (c) Bitstream (see below). DejaVu changes are in public domain.
|
||||||
|
|
||||||
|
Math extensions done by B. Jackowski, P. Strzelczyk and P. Pianowski
|
||||||
|
(on behalf of TeX users groups) are in public domain.
|
||||||
|
|
||||||
|
Letters imported from Euler Fraktur from AMSfonts are (c) American
|
||||||
|
Mathematical Society (see below).
|
||||||
|
Bitstream Vera Fonts Copyright
|
||||||
|
Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera
|
||||||
|
is a trademark of Bitstream, Inc.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of the fonts accompanying this license (“Fonts”) and associated
|
||||||
|
documentation
|
||||||
|
files (the “Font Software”), to reproduce and distribute the Font Software,
|
||||||
|
including without limitation the rights to use, copy, merge, publish,
|
||||||
|
distribute,
|
||||||
|
and/or sell copies of the Font Software, and to permit persons to whom
|
||||||
|
the Font Software is furnished to do so, subject to the following
|
||||||
|
conditions:
|
||||||
|
|
||||||
|
The above copyright and trademark notices and this permission notice
|
||||||
|
shall be
|
||||||
|
included in all copies of one or more of the Font Software typefaces.
|
||||||
|
|
||||||
|
The Font Software may be modified, altered, or added to, and in particular
|
||||||
|
the designs of glyphs or characters in the Fonts may be modified and
|
||||||
|
additional
|
||||||
|
glyphs or characters may be added to the Fonts, only if the fonts are
|
||||||
|
renamed
|
||||||
|
to names not containing either the words “Bitstream” or the word “Vera”.
|
||||||
|
|
||||||
|
This License becomes null and void to the extent applicable to Fonts or
|
||||||
|
Font Software
|
||||||
|
that has been modified and is distributed under the “Bitstream Vera”
|
||||||
|
names.
|
||||||
|
|
||||||
|
The Font Software may be sold as part of a larger software package but
|
||||||
|
no copy
|
||||||
|
of one or more of the Font Software typefaces may be sold by itself.
|
||||||
|
|
||||||
|
THE FONT SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT,
|
||||||
|
TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME
|
||||||
|
FOUNDATION
|
||||||
|
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL,
|
||||||
|
SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN
|
||||||
|
ACTION
|
||||||
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR
|
||||||
|
INABILITY TO USE
|
||||||
|
THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE.
|
||||||
|
Except as contained in this notice, the names of GNOME, the GNOME
|
||||||
|
Foundation,
|
||||||
|
and Bitstream Inc., shall not be used in advertising or otherwise to promote
|
||||||
|
the sale, use or other dealings in this Font Software without prior written
|
||||||
|
authorization from the GNOME Foundation or Bitstream Inc., respectively.
|
||||||
|
For further information, contact: fonts at gnome dot org.
|
||||||
|
|
||||||
|
AMSFonts (v. 2.2) copyright
|
||||||
|
|
||||||
|
The PostScript Type 1 implementation of the AMSFonts produced by and
|
||||||
|
previously distributed by Blue Sky Research and Y&Y, Inc. are now freely
|
||||||
|
available for general use. This has been accomplished through the
|
||||||
|
cooperation
|
||||||
|
of a consortium of scientific publishers with Blue Sky Research and Y&Y.
|
||||||
|
Members of this consortium include:
|
||||||
|
|
||||||
|
Elsevier Science IBM Corporation Society for Industrial and Applied
|
||||||
|
Mathematics (SIAM) Springer-Verlag American Mathematical Society (AMS)
|
||||||
|
|
||||||
|
In order to assure the authenticity of these fonts, copyright will be
|
||||||
|
held by
|
||||||
|
the American Mathematical Society. This is not meant to restrict in any way
|
||||||
|
the legitimate use of the fonts, such as (but not limited to) electronic
|
||||||
|
distribution of documents containing these fonts, inclusion of these fonts
|
||||||
|
into other public domain or commercial font collections or computer
|
||||||
|
applications, use of the outline data to create derivative fonts and/or
|
||||||
|
faces, etc. However, the AMS does require that the AMS copyright notice be
|
||||||
|
removed from any derivative versions of the fonts which have been altered in
|
||||||
|
any way. In addition, to ensure the fidelity of TeX documents using Computer
|
||||||
|
Modern fonts, Professor Donald Knuth, creator of the Computer Modern faces,
|
||||||
|
has requested that any alterations which yield different font metrics be
|
||||||
|
given a different name.
|
||||||
|
|
||||||
|
$Id$
|
1
assets/dummy.vtt
Normal file
1
assets/dummy.vtt
Normal file
@ -0,0 +1 @@
|
|||||||
|
WEBVTT
|
@ -78,7 +78,6 @@ static-files = "0.2"
|
|||||||
name = "ffplayout"
|
name = "ffplayout"
|
||||||
path = "src/main.rs"
|
path = "src/main.rs"
|
||||||
|
|
||||||
|
|
||||||
# DEBIAN DEB PACKAGE
|
# DEBIAN DEB PACKAGE
|
||||||
[package.metadata.deb]
|
[package.metadata.deb]
|
||||||
name = "ffplayout"
|
name = "ffplayout"
|
||||||
@ -99,6 +98,21 @@ assets = [
|
|||||||
"/lib/systemd/system/",
|
"/lib/systemd/system/",
|
||||||
"644",
|
"644",
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
"../assets/dummy.vtt",
|
||||||
|
"/usr/share/ffplayout/",
|
||||||
|
"644",
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"../assets/DejaVuSans.ttf",
|
||||||
|
"/usr/share/ffplayout/",
|
||||||
|
"644",
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"../assets/FONT_LICENSE.txt",
|
||||||
|
"/usr/share/ffplayout/",
|
||||||
|
"644",
|
||||||
|
],
|
||||||
[
|
[
|
||||||
"../assets/logo.png",
|
"../assets/logo.png",
|
||||||
"/usr/share/ffplayout/",
|
"/usr/share/ffplayout/",
|
||||||
@ -135,6 +149,21 @@ assets = [
|
|||||||
"/lib/systemd/system/",
|
"/lib/systemd/system/",
|
||||||
"644",
|
"644",
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
"../assets/dummy.vtt",
|
||||||
|
"/usr/share/ffplayout/",
|
||||||
|
"644",
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"../assets/DejaVuSans.ttf",
|
||||||
|
"/usr/share/ffplayout/",
|
||||||
|
"644",
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"../assets/FONT_LICENSE.txt",
|
||||||
|
"/usr/share/ffplayout/",
|
||||||
|
"644",
|
||||||
|
],
|
||||||
[
|
[
|
||||||
"../assets/logo.png",
|
"../assets/logo.png",
|
||||||
"/usr/share/ffplayout/",
|
"/usr/share/ffplayout/",
|
||||||
@ -157,7 +186,7 @@ assets = [
|
|||||||
],
|
],
|
||||||
]
|
]
|
||||||
|
|
||||||
# REHL RPM PACKAGE
|
# RHEL RPM PACKAGE
|
||||||
[package.metadata.generate-rpm]
|
[package.metadata.generate-rpm]
|
||||||
name = "ffplayout"
|
name = "ffplayout"
|
||||||
license = "GPL-3.0"
|
license = "GPL-3.0"
|
||||||
@ -167,6 +196,9 @@ assets = [
|
|||||||
{ source = "../README.md", dest = "/usr/share/doc/ffplayout/README", mode = "644" },
|
{ source = "../README.md", dest = "/usr/share/doc/ffplayout/README", mode = "644" },
|
||||||
{ source = "../assets/ffplayout.1.gz", dest = "/usr/share/man/man1/ffplayout.1.gz", mode = "644", doc = true },
|
{ source = "../assets/ffplayout.1.gz", dest = "/usr/share/man/man1/ffplayout.1.gz", mode = "644", doc = true },
|
||||||
{ source = "../LICENSE", dest = "/usr/share/doc/ffplayout/LICENSE", mode = "644" },
|
{ source = "../LICENSE", dest = "/usr/share/doc/ffplayout/LICENSE", mode = "644" },
|
||||||
|
{ source = "../assets/dummy.vtt", dest = "/usr/share/ffplayout/dummy.vtt", mode = "644" },
|
||||||
|
{ source = "../assets/DejaVuSans.ttf", dest = "/usr/share/ffplayout/DejaVuSans.ttf", mode = "644" },
|
||||||
|
{ source = "../assets/FONT_LICENSE.txt", dest = "/usr/share/ffplayout/FONT_LICENSE.txt", mode = "644" },
|
||||||
{ source = "../assets/logo.png", dest = "/usr/share/ffplayout/logo.png", mode = "644" },
|
{ source = "../assets/logo.png", dest = "/usr/share/ffplayout/logo.png", mode = "644" },
|
||||||
{ source = "../assets/ffplayout.conf", dest = "/usr/share/ffplayout/ffplayout.conf.example", mode = "644" },
|
{ source = "../assets/ffplayout.conf", dest = "/usr/share/ffplayout/ffplayout.conf.example", mode = "644" },
|
||||||
{ source = "../debian/postinst", dest = "/usr/share/ffplayout/postinst", mode = "755" },
|
{ source = "../debian/postinst", dest = "/usr/share/ffplayout/postinst", mode = "755" },
|
||||||
|
@ -480,7 +480,11 @@ async fn patch_channel(
|
|||||||
role: AuthDetails<Role>,
|
role: AuthDetails<Role>,
|
||||||
user: web::ReqData<UserMeta>,
|
user: web::ReqData<UserMeta>,
|
||||||
) -> Result<impl Responder, ServiceError> {
|
) -> Result<impl Responder, ServiceError> {
|
||||||
let manager = controllers.lock().unwrap().get(*id).unwrap();
|
let manager = controllers
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.get(*id)
|
||||||
|
.ok_or(format!("Channel {id} not found!"))?;
|
||||||
let mut data = data.into_inner();
|
let mut data = data.into_inner();
|
||||||
|
|
||||||
if !role.has_authority(&Role::GlobalAdmin) {
|
if !role.has_authority(&Role::GlobalAdmin) {
|
||||||
|
@ -302,6 +302,10 @@ pub struct Configuration {
|
|||||||
pub processing_volume: f64,
|
pub processing_volume: f64,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub processing_filter: String,
|
pub processing_filter: String,
|
||||||
|
#[serde(default)]
|
||||||
|
pub processing_vtt_enable: bool,
|
||||||
|
#[serde(default)]
|
||||||
|
pub processing_vtt_dummy: Option<String>,
|
||||||
|
|
||||||
pub ingest_help: String,
|
pub ingest_help: String,
|
||||||
pub ingest_enable: bool,
|
pub ingest_enable: bool,
|
||||||
@ -375,6 +379,8 @@ impl Configuration {
|
|||||||
processing_audio_channels: config.processing.audio_channels,
|
processing_audio_channels: config.processing.audio_channels,
|
||||||
processing_volume: config.processing.volume,
|
processing_volume: config.processing.volume,
|
||||||
processing_filter: config.processing.custom_filter,
|
processing_filter: config.processing.custom_filter,
|
||||||
|
processing_vtt_enable: config.processing.vtt_enable,
|
||||||
|
processing_vtt_dummy: config.processing.vtt_dummy,
|
||||||
ingest_help: config.ingest.help_text,
|
ingest_help: config.ingest.help_text,
|
||||||
ingest_enable: config.ingest.enable,
|
ingest_enable: config.ingest.enable,
|
||||||
ingest_param: config.ingest.input_param,
|
ingest_param: config.ingest.input_param,
|
||||||
|
@ -199,6 +199,8 @@ async fn main() -> std::io::Result<()> {
|
|||||||
.workers(thread_count)
|
.workers(thread_count)
|
||||||
.run()
|
.run()
|
||||||
.await?;
|
.await?;
|
||||||
|
} else if ARGS.drop_db {
|
||||||
|
db_drop().await;
|
||||||
} else {
|
} else {
|
||||||
let channels = ARGS.channels.clone().unwrap_or_else(|| vec![1]);
|
let channels = ARGS.channels.clone().unwrap_or_else(|| vec![1]);
|
||||||
|
|
||||||
@ -267,8 +269,6 @@ async fn main() -> std::io::Result<()> {
|
|||||||
playlist,
|
playlist,
|
||||||
Arc::new(AtomicBool::new(false)),
|
Arc::new(AtomicBool::new(false)),
|
||||||
);
|
);
|
||||||
} else if ARGS.drop_db {
|
|
||||||
db_drop().await;
|
|
||||||
} else if !ARGS.init {
|
} else if !ARGS.init {
|
||||||
error!("Run ffplayout with parameters! Run ffplayout -h for more information.");
|
error!("Run ffplayout with parameters! Run ffplayout -h for more information.");
|
||||||
}
|
}
|
||||||
|
@ -4,11 +4,12 @@ use std::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(target_family = "unix")]
|
#[cfg(target_family = "unix")]
|
||||||
use std::{fs, process::exit};
|
use std::process::exit;
|
||||||
|
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use rpassword::read_password;
|
use rpassword::read_password;
|
||||||
use sqlx::{Pool, Sqlite};
|
use sqlx::{Pool, Sqlite};
|
||||||
|
use tokio::fs;
|
||||||
|
|
||||||
use crate::db::{
|
use crate::db::{
|
||||||
handles,
|
handles,
|
||||||
@ -17,6 +18,7 @@ use crate::db::{
|
|||||||
use crate::utils::{
|
use crate::utils::{
|
||||||
advanced_config::AdvancedConfig,
|
advanced_config::AdvancedConfig,
|
||||||
config::{OutputMode, PlayoutConfig},
|
config::{OutputMode, PlayoutConfig},
|
||||||
|
copy_assets,
|
||||||
};
|
};
|
||||||
use crate::ARGS;
|
use crate::ARGS;
|
||||||
|
|
||||||
@ -197,6 +199,13 @@ fn global_user(args: &mut Args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn run_args(pool: &Pool<Sqlite>) -> Result<(), i32> {
|
pub async fn run_args(pool: &Pool<Sqlite>) -> Result<(), i32> {
|
||||||
|
let mut user = None;
|
||||||
|
let mut fix_permission = false;
|
||||||
|
|
||||||
|
if cfg!(target_family = "unix") {
|
||||||
|
user = nix::unistd::User::from_name("ffpu").unwrap_or_default();
|
||||||
|
}
|
||||||
|
|
||||||
let mut args = ARGS.clone();
|
let mut args = ARGS.clone();
|
||||||
|
|
||||||
if !args.dump_advanced && !args.dump_config && !args.drop_db {
|
if !args.dump_advanced && !args.dump_config && !args.drop_db {
|
||||||
@ -212,18 +221,12 @@ pub async fn run_args(pool: &Pool<Sqlite>) -> Result<(), i32> {
|
|||||||
let mut error_code = -1;
|
let mut error_code = -1;
|
||||||
|
|
||||||
if args.init {
|
if args.init {
|
||||||
#[cfg(target_family = "unix")]
|
|
||||||
let process_user = nix::unistd::User::from_name("ffpu").unwrap_or_default();
|
|
||||||
|
|
||||||
#[cfg(target_family = "unix")]
|
|
||||||
let mut fix_permission = false;
|
|
||||||
|
|
||||||
#[cfg(target_family = "unix")]
|
#[cfg(target_family = "unix")]
|
||||||
{
|
{
|
||||||
let uid = nix::unistd::Uid::current();
|
let uid = nix::unistd::Uid::current();
|
||||||
let current_user = nix::unistd::User::from_uid(uid).unwrap_or_default();
|
let current_user = nix::unistd::User::from_uid(uid).unwrap_or_default();
|
||||||
|
|
||||||
if current_user != process_user {
|
if current_user != user {
|
||||||
let user_name = current_user.unwrap().name;
|
let user_name = current_user.unwrap().name;
|
||||||
let mut fix_perm = String::new();
|
let mut fix_perm = String::new();
|
||||||
|
|
||||||
@ -353,7 +356,11 @@ pub async fn run_args(pool: &Pool<Sqlite>) -> Result<(), i32> {
|
|||||||
channel.playlist_path = global.playlist_root;
|
channel.playlist_path = global.playlist_root;
|
||||||
channel.storage_path = global.storage_root;
|
channel.storage_path = global.storage_root;
|
||||||
|
|
||||||
|
let mut storage_path = PathBuf::from(channel.storage_path.clone());
|
||||||
|
|
||||||
if global.shared_storage {
|
if global.shared_storage {
|
||||||
|
storage_path = storage_path.join("1");
|
||||||
|
|
||||||
channel.preview_url = "http://127.0.0.1:8787/1/stream.m3u8".to_string();
|
channel.preview_url = "http://127.0.0.1:8787/1/stream.m3u8".to_string();
|
||||||
channel.hls_path = Path::new(&channel.hls_path)
|
channel.hls_path = Path::new(&channel.hls_path)
|
||||||
.join("1")
|
.join("1")
|
||||||
@ -363,22 +370,27 @@ pub async fn run_args(pool: &Pool<Sqlite>) -> Result<(), i32> {
|
|||||||
.join("1")
|
.join("1")
|
||||||
.to_string_lossy()
|
.to_string_lossy()
|
||||||
.to_string();
|
.to_string();
|
||||||
channel.storage_path = Path::new(&channel.storage_path)
|
channel.storage_path = storage_path.to_string_lossy().to_string();
|
||||||
.join("1")
|
};
|
||||||
.to_string_lossy()
|
|
||||||
.to_string();
|
if let Err(e) = copy_assets(&storage_path, fix_permission, user.clone()).await {
|
||||||
|
eprintln!("{e}");
|
||||||
};
|
};
|
||||||
|
|
||||||
handles::update_channel(pool, 1, channel).await.unwrap();
|
handles::update_channel(pool, 1, channel).await.unwrap();
|
||||||
|
|
||||||
#[cfg(target_family = "unix")]
|
#[cfg(target_family = "unix")]
|
||||||
if fix_permission {
|
if fix_permission {
|
||||||
let db_path = Path::new(db_path().unwrap()).with_extension("");
|
let user = user.clone().unwrap();
|
||||||
let user = process_user.unwrap();
|
let db_path = Path::new(db_path().unwrap());
|
||||||
|
|
||||||
let db = fs::canonicalize(db_path.with_extension("db")).unwrap();
|
let db = fs::canonicalize(db_path).await.unwrap();
|
||||||
let shm = fs::canonicalize(db_path.with_extension("db-shm")).unwrap();
|
let shm = fs::canonicalize(db_path.with_extension("db-shm"))
|
||||||
let wal = fs::canonicalize(db_path.with_extension("db-wal")).unwrap();
|
.await
|
||||||
|
.unwrap();
|
||||||
|
let wal = fs::canonicalize(db_path.with_extension("db-wal"))
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
nix::unistd::chown(&db, Some(user.uid), Some(user.gid)).expect("Change DB owner");
|
nix::unistd::chown(&db, Some(user.uid), Some(user.gid)).expect("Change DB owner");
|
||||||
|
|
||||||
@ -410,7 +422,7 @@ pub async fn run_args(pool: &Pool<Sqlite>) -> Result<(), i32> {
|
|||||||
|
|
||||||
let chl: Vec<i32> = channels.clone().iter().map(|c| c.id).collect();
|
let chl: Vec<i32> = channels.clone().iter().map(|c| c.id).collect();
|
||||||
|
|
||||||
let user = User {
|
let ff_user = User {
|
||||||
id: 0,
|
id: 0,
|
||||||
mail: Some(args.mail.unwrap()),
|
mail: Some(args.mail.unwrap()),
|
||||||
username: username.clone(),
|
username: username.clone(),
|
||||||
@ -420,7 +432,7 @@ pub async fn run_args(pool: &Pool<Sqlite>) -> Result<(), i32> {
|
|||||||
token: None,
|
token: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Err(e) = handles::insert_user(pool, user).await {
|
if let Err(e) = handles::insert_user(pool, ff_user).await {
|
||||||
eprintln!("{e}");
|
eprintln!("{e}");
|
||||||
error_code = 1;
|
error_code = 1;
|
||||||
};
|
};
|
||||||
@ -449,8 +461,11 @@ pub async fn run_args(pool: &Pool<Sqlite>) -> Result<(), i32> {
|
|||||||
let mut channel = handles::select_channel(pool, &1)
|
let mut channel = handles::select_channel(pool, &1)
|
||||||
.await
|
.await
|
||||||
.expect("Select Channel 1");
|
.expect("Select Channel 1");
|
||||||
|
let mut storage_path = PathBuf::from(global.storage_root.clone());
|
||||||
|
|
||||||
if args.shared_storage {
|
if args.shared_storage {
|
||||||
|
storage_path = storage_path.join("1");
|
||||||
|
|
||||||
channel.hls_path = Path::new(&global.public_root)
|
channel.hls_path = Path::new(&global.public_root)
|
||||||
.join("1")
|
.join("1")
|
||||||
.to_string_lossy()
|
.to_string_lossy()
|
||||||
@ -459,16 +474,17 @@ pub async fn run_args(pool: &Pool<Sqlite>) -> Result<(), i32> {
|
|||||||
.join("1")
|
.join("1")
|
||||||
.to_string_lossy()
|
.to_string_lossy()
|
||||||
.to_string();
|
.to_string();
|
||||||
channel.storage_path = Path::new(&global.storage_root)
|
channel.storage_path = storage_path.to_string_lossy().to_string();
|
||||||
.join("1")
|
|
||||||
.to_string_lossy()
|
|
||||||
.to_string();
|
|
||||||
} else {
|
} else {
|
||||||
channel.hls_path = global.public_root.clone();
|
channel.hls_path = global.public_root.clone();
|
||||||
channel.playlist_path = global.playlist_root.clone();
|
channel.playlist_path = global.playlist_root.clone();
|
||||||
channel.storage_path = global.storage_root.clone();
|
channel.storage_path = global.storage_root.clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Err(e) = copy_assets(&storage_path, false, user).await {
|
||||||
|
eprintln!("{e}");
|
||||||
|
};
|
||||||
|
|
||||||
match handles::update_global(pool, global.clone()).await {
|
match handles::update_global(pool, global.clone()).await {
|
||||||
Ok(_) => println!("Update globals done..."),
|
Ok(_) => println!("Update globals done..."),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
use std::{
|
use std::{
|
||||||
ffi::OsStr,
|
|
||||||
io,
|
io,
|
||||||
path::Path,
|
path::PathBuf,
|
||||||
sync::{Arc, Mutex},
|
sync::{Arc, Mutex},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -11,7 +10,7 @@ use sqlx::{Pool, Sqlite};
|
|||||||
use super::logging::MailQueue;
|
use super::logging::MailQueue;
|
||||||
use crate::db::{handles, models::Channel};
|
use crate::db::{handles, models::Channel};
|
||||||
use crate::player::controller::{ChannelController, ChannelManager};
|
use crate::player::controller::{ChannelController, ChannelManager};
|
||||||
use crate::utils::{config::get_config, errors::ServiceError};
|
use crate::utils::{config::get_config, copy_assets, errors::ServiceError};
|
||||||
|
|
||||||
async fn map_global_admins(conn: &Pool<Sqlite>) -> Result<(), ServiceError> {
|
async fn map_global_admins(conn: &Pool<Sqlite>) -> Result<(), ServiceError> {
|
||||||
let channels = handles::select_related_channels(conn, None).await?;
|
let channels = handles::select_related_channels(conn, None).await?;
|
||||||
@ -29,58 +28,32 @@ async fn map_global_admins(conn: &Pool<Sqlite>) -> Result<(), ServiceError> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn preview_url(url: &str, id: i32) -> String {
|
|
||||||
let url_path = Path::new(url);
|
|
||||||
|
|
||||||
if let Some(parent) = url_path.parent() {
|
|
||||||
if let Some(filename) = url_path.file_name() {
|
|
||||||
let new_path = if parent
|
|
||||||
.file_name()
|
|
||||||
.unwrap_or_else(|| OsStr::new("0"))
|
|
||||||
.to_string_lossy()
|
|
||||||
.to_string()
|
|
||||||
.parse::<i32>()
|
|
||||||
.is_ok()
|
|
||||||
{
|
|
||||||
parent.join(filename)
|
|
||||||
} else {
|
|
||||||
parent.join(id.to_string()).join(filename)
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Some(new_url) = new_path.to_str() {
|
|
||||||
return new_url.to_string();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
url.to_string()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn create_channel(
|
pub async fn create_channel(
|
||||||
conn: &Pool<Sqlite>,
|
conn: &Pool<Sqlite>,
|
||||||
controllers: Arc<Mutex<ChannelController>>,
|
controllers: Arc<Mutex<ChannelController>>,
|
||||||
queue: Arc<Mutex<Vec<Arc<Mutex<MailQueue>>>>>,
|
queue: Arc<Mutex<Vec<Arc<Mutex<MailQueue>>>>>,
|
||||||
target_channel: Channel,
|
target_channel: Channel,
|
||||||
) -> Result<Channel, ServiceError> {
|
) -> Result<Channel, ServiceError> {
|
||||||
let global = handles::select_global(conn).await?;
|
let channel = handles::insert_channel(conn, target_channel).await?;
|
||||||
let mut channel = handles::insert_channel(conn, target_channel).await?;
|
let storage_path = PathBuf::from(channel.storage_path.clone());
|
||||||
|
let mut user = None;
|
||||||
|
let mut fix_permission = false;
|
||||||
|
|
||||||
|
if cfg!(target_family = "unix") {
|
||||||
|
user = nix::unistd::User::from_name("ffpu").unwrap_or_default();
|
||||||
|
let uid = nix::unistd::Uid::current();
|
||||||
|
let current_user = nix::unistd::User::from_uid(uid).unwrap_or_default();
|
||||||
|
|
||||||
|
if current_user.unwrap().name == "root" {
|
||||||
|
fix_permission = true;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
handles::new_channel_presets(conn, channel.id).await?;
|
handles::new_channel_presets(conn, channel.id).await?;
|
||||||
|
|
||||||
channel.preview_url = preview_url(&channel.preview_url, channel.id);
|
if let Err(e) = copy_assets(&storage_path, fix_permission, user).await {
|
||||||
|
error!("{e}");
|
||||||
if global.shared_storage {
|
};
|
||||||
channel.hls_path = Path::new(&global.public_root)
|
|
||||||
.join(channel.id.to_string())
|
|
||||||
.to_string_lossy()
|
|
||||||
.to_string();
|
|
||||||
channel.playlist_path = Path::new(&global.playlist_root)
|
|
||||||
.join(channel.id.to_string())
|
|
||||||
.to_string_lossy()
|
|
||||||
.to_string();
|
|
||||||
channel.storage_path = Path::new(&global.storage_root)
|
|
||||||
.join(channel.id.to_string())
|
|
||||||
.to_string_lossy()
|
|
||||||
.to_string();
|
|
||||||
}
|
|
||||||
|
|
||||||
handles::update_channel(conn, channel.id, channel.clone()).await?;
|
handles::update_channel(conn, channel.id, channel.clone()).await?;
|
||||||
|
|
||||||
|
@ -328,6 +328,8 @@ pub struct Processing {
|
|||||||
pub audio_channels: u8,
|
pub audio_channels: u8,
|
||||||
pub volume: f64,
|
pub volume: f64,
|
||||||
pub custom_filter: String,
|
pub custom_filter: String,
|
||||||
|
pub vtt_enable: bool,
|
||||||
|
pub vtt_dummy: Option<String>,
|
||||||
#[serde(skip_serializing, skip_deserializing)]
|
#[serde(skip_serializing, skip_deserializing)]
|
||||||
pub cmd: Option<Vec<String>>,
|
pub cmd: Option<Vec<String>>,
|
||||||
}
|
}
|
||||||
@ -355,6 +357,8 @@ impl Processing {
|
|||||||
audio_channels: config.processing_audio_channels,
|
audio_channels: config.processing_audio_channels,
|
||||||
volume: config.processing_volume,
|
volume: config.processing_volume,
|
||||||
custom_filter: config.processing_filter.clone(),
|
custom_filter: config.processing_filter.clone(),
|
||||||
|
vtt_enable: config.processing_vtt_enable,
|
||||||
|
vtt_dummy: config.processing_vtt_dummy.clone(),
|
||||||
cmd: None,
|
cmd: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -310,3 +310,54 @@ pub fn round_to_nearest_ten(num: i64) -> i64 {
|
|||||||
(num / 10) * 10
|
(num / 10) * 10
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn copy_assets(
|
||||||
|
storage_path: &Path,
|
||||||
|
fix_permission: bool,
|
||||||
|
user: Option<nix::unistd::User>,
|
||||||
|
) -> Result<(), std::io::Error> {
|
||||||
|
if storage_path.is_dir() {
|
||||||
|
let target = storage_path.join("00-assets");
|
||||||
|
let mut dummy_source = Path::new("/usr/share/ffplayout/dummy.vtt");
|
||||||
|
let mut font_source = Path::new("/usr/share/ffplayout/DejaVuSans.ttf");
|
||||||
|
let mut logo_source = Path::new("/usr/share/ffplayout/logo.png");
|
||||||
|
|
||||||
|
if !dummy_source.is_file() {
|
||||||
|
dummy_source = Path::new("./assets/dummy.vtt")
|
||||||
|
}
|
||||||
|
if !font_source.is_file() {
|
||||||
|
font_source = Path::new("./assets/DejaVuSans.ttf")
|
||||||
|
}
|
||||||
|
if !logo_source.is_file() {
|
||||||
|
logo_source = Path::new("./assets/logo.png")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !target.is_dir() {
|
||||||
|
let dummy_target = target.join("dummy.vtt");
|
||||||
|
let font_target = target.join("DejaVuSans.ttf");
|
||||||
|
let logo_target = target.join("logo.png");
|
||||||
|
|
||||||
|
fs::create_dir(&target).await?;
|
||||||
|
fs::copy(&dummy_source, &dummy_target).await?;
|
||||||
|
fs::copy(&font_source, &font_target).await?;
|
||||||
|
fs::copy(&logo_source, &logo_target).await?;
|
||||||
|
|
||||||
|
#[cfg(target_family = "unix")]
|
||||||
|
if fix_permission {
|
||||||
|
let user = user.unwrap();
|
||||||
|
|
||||||
|
if dummy_target.is_file() {
|
||||||
|
nix::unistd::chown(&dummy_target, Some(user.uid), Some(user.gid))?;
|
||||||
|
}
|
||||||
|
if font_target.is_file() {
|
||||||
|
nix::unistd::chown(&font_target, Some(user.uid), Some(user.gid))?;
|
||||||
|
}
|
||||||
|
if logo_target.is_file() {
|
||||||
|
nix::unistd::chown(&logo_target, Some(user.uid), Some(user.gid))?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
@ -120,7 +120,7 @@ function newChannel() {
|
|||||||
|
|
||||||
newChannel.id = channels.length + 1
|
newChannel.id = channels.length + 1
|
||||||
newChannel.name = `Channel ${newChannel.id}`
|
newChannel.name = `Channel ${newChannel.id}`
|
||||||
newChannel.preview_url = `${window.location.protocol}//${window.location.host}/live/${newChannel.id}/stream.m3u8`
|
newChannel.preview_url = `${window.location.protocol}//${window.location.host}/${newChannel.id}/live/stream.m3u8`
|
||||||
newChannel.hls_path = `${rmId(newChannel.hls_path)}/${newChannel.id}`
|
newChannel.hls_path = `${rmId(newChannel.hls_path)}/${newChannel.id}`
|
||||||
newChannel.playlist_path = `${rmId(newChannel.playlist_path)}/${newChannel.id}`
|
newChannel.playlist_path = `${rmId(newChannel.playlist_path)}/${newChannel.id}`
|
||||||
newChannel.storage_path = `${rmId(newChannel.storage_path)}/${newChannel.id}`
|
newChannel.storage_path = `${rmId(newChannel.storage_path)}/${newChannel.id}`
|
||||||
@ -158,6 +158,7 @@ async function deleteChannel() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
config.splice(configStore.id, 1)
|
config.splice(configStore.id, 1)
|
||||||
|
configStore.channelsRaw.splice(configStore.id, 1)
|
||||||
configStore.channels = config
|
configStore.channels = config
|
||||||
configStore.id = configStore.channels.length - 1
|
configStore.id = configStore.channels.length - 1
|
||||||
|
|
||||||
|
@ -15,7 +15,15 @@
|
|||||||
class="form-control w-full"
|
class="form-control w-full"
|
||||||
:class="[typeof prop === 'boolean' && 'flex-row', name.toString() !== 'help_text' && 'mt-2']"
|
:class="[typeof prop === 'boolean' && 'flex-row', name.toString() !== 'help_text' && 'mt-2']"
|
||||||
>
|
>
|
||||||
<template v-if="name.toString() !== 'startInSec' && name.toString() !== 'lengthInSec' && !(name.toString() === 'path' && key.toString() === 'storage')" >
|
<!-- TODO: vtt_ check is temporary, needs to be removed when is done implemented -->
|
||||||
|
<template
|
||||||
|
v-if="
|
||||||
|
name.toString() !== 'startInSec' &&
|
||||||
|
name.toString() !== 'lengthInSec' &&
|
||||||
|
!name.startsWith('vtt_') &&
|
||||||
|
!(name.toString() === 'path' && key.toString() === 'storage')
|
||||||
|
"
|
||||||
|
>
|
||||||
<div v-if="name.toString() !== 'help_text'" class="label">
|
<div v-if="name.toString() !== 'help_text'" class="label">
|
||||||
<span class="label-text !text-md font-bold">{{ name }}</span>
|
<span class="label-text !text-md font-bold">{{ name }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="grid grid-cols-1 xs:grid-cols-2 border-4 rounded-md border-primary text-left shadow min-w-[320px] max-w-[960px] mt-5 xs:mt-0">
|
<div class="grid grid-cols-1 xs:grid-cols-2 border-4 rounded-md border-primary text-left shadow min-w-[320px] md:min-w-[728px] max-w-[960px] mt-5 xs:mt-0">
|
||||||
<div class="p-4 bg-base-100">
|
<div class="p-4 bg-base-100">
|
||||||
<span class="text-3xl">{{ sysStat.system.name }} {{ sysStat.system.version }}</span>
|
<span class="text-3xl">{{ sysStat.system.name }} {{ sysStat.system.version }}</span>
|
||||||
<span v-if="sysStat.system.kernel">
|
<span v-if="sysStat.system.kernel">
|
||||||
|
@ -104,7 +104,7 @@ CREATE TABLE
|
|||||||
processing_aspect REAL NOT NULL DEFAULT 1.778,
|
processing_aspect REAL NOT NULL DEFAULT 1.778,
|
||||||
processing_fps REAL NOT NULL DEFAULT 25.0,
|
processing_fps REAL NOT NULL DEFAULT 25.0,
|
||||||
processing_add_logo INTEGER NOT NULL DEFAULT 1,
|
processing_add_logo INTEGER NOT NULL DEFAULT 1,
|
||||||
processing_logo TEXT NOT NULL DEFAULT "graphics/logo.png",
|
processing_logo TEXT NOT NULL DEFAULT "00-assets/logo.png",
|
||||||
processing_logo_scale TEXT NOT NULL DEFAULT "",
|
processing_logo_scale TEXT NOT NULL DEFAULT "",
|
||||||
processing_logo_opacity REAL NOT NULL DEFAULT 0.7,
|
processing_logo_opacity REAL NOT NULL DEFAULT 0.7,
|
||||||
processing_logo_position TEXT NOT NULL DEFAULT "W-w-12:12",
|
processing_logo_position TEXT NOT NULL DEFAULT "W-w-12:12",
|
||||||
@ -113,6 +113,8 @@ CREATE TABLE
|
|||||||
processing_audio_channels INTEGER NOT NULL DEFAULT 2,
|
processing_audio_channels INTEGER NOT NULL DEFAULT 2,
|
||||||
processing_volume REAL NOT NULL DEFAULT 1.0,
|
processing_volume REAL NOT NULL DEFAULT 1.0,
|
||||||
processing_filter TEXT NOT NULL DEFAULT "",
|
processing_filter TEXT NOT NULL DEFAULT "",
|
||||||
|
processing_vtt_enable INTEGER NOT NULL DEFAULT 0,
|
||||||
|
processing_vtt_dummy TEXT NULL DEFAULT "00-assets/dummy.vtt",
|
||||||
ingest_help "Run a server for a ingest stream. This stream will override the normal streaming until is done. There is only a very simple authentication mechanism, which check if the stream name is correct.\n'custom_filter' can be used in the same way then the one in the process section.",
|
ingest_help "Run a server for a ingest stream. This stream will override the normal streaming until is done. There is only a very simple authentication mechanism, which check if the stream name is correct.\n'custom_filter' can be used in the same way then the one in the process section.",
|
||||||
ingest_enable INTEGER NOT NULL DEFAULT 0,
|
ingest_enable INTEGER NOT NULL DEFAULT 0,
|
||||||
ingest_param TEXT NOT NULL DEFAULT "-f live_flv -listen 1 -i rtmp://127.0.0.1:1936/live/stream",
|
ingest_param TEXT NOT NULL DEFAULT "-f live_flv -listen 1 -i rtmp://127.0.0.1:1936/live/stream",
|
||||||
@ -128,7 +130,7 @@ CREATE TABLE
|
|||||||
text_help TEXT NOT NULL DEFAULT "Overlay text in combination with libzmq for remote text manipulation. fontfile is a relative path to your storage folder.\n'text_from_filename' activate the extraction from text of a filename. With 'style' you can define the drawtext parameters like position, color, etc. Post Text over API will override this. With 'regex' you can format file names, to get a title from it.",
|
text_help TEXT NOT NULL DEFAULT "Overlay text in combination with libzmq for remote text manipulation. fontfile is a relative path to your storage folder.\n'text_from_filename' activate the extraction from text of a filename. With 'style' you can define the drawtext parameters like position, color, etc. Post Text over API will override this. With 'regex' you can format file names, to get a title from it.",
|
||||||
text_add INTEGER NOT NULL DEFAULT 1,
|
text_add INTEGER NOT NULL DEFAULT 1,
|
||||||
text_from_filename INTEGER NOT NULL DEFAULT 0,
|
text_from_filename INTEGER NOT NULL DEFAULT 0,
|
||||||
text_font TEXT NOT NULL DEFAULT "fonts/DejaVuSans.ttf",
|
text_font TEXT NOT NULL DEFAULT "00-assets/DejaVuSans.ttf",
|
||||||
text_style TEXT NOT NULL DEFAULT "x=(w-tw)/2:y=(h-line_h)*0.9:fontsize=24:fontcolor=#ffffff:box=1:boxcolor=#000000:boxborderw=4",
|
text_style TEXT NOT NULL DEFAULT "x=(w-tw)/2:y=(h-line_h)*0.9:fontsize=24:fontcolor=#ffffff:box=1:boxcolor=#000000:boxborderw=4",
|
||||||
text_regex TEXT NOT NULL DEFAULT "^.+[/\\](.*)(.mp4|.mkv|.webm)$",
|
text_regex TEXT NOT NULL DEFAULT "^.+[/\\](.*)(.mp4|.mkv|.webm)$",
|
||||||
task_help TEXT NOT NULL DEFAULT "Run an external program with a given media object. The media object is in json format and contains all the information about the current clip. The external program can be a script or a binary, but should only run for a short time.",
|
task_help TEXT NOT NULL DEFAULT "Run an external program with a given media object. The media object is in json format and contains all the information about the current clip. The external program can be a script or a binary, but should only run for a short time.",
|
||||||
|
Loading…
Reference in New Issue
Block a user