remove shared argument

This commit is contained in:
Jonathan Baecker 2024-10-18 12:29:52 +02:00
parent 5fba77f9ac
commit a842c78d99
15 changed files with 1490 additions and 715 deletions

View File

@ -12,7 +12,10 @@ COPY <<-EOT /run.sh
#!/bin/sh #!/bin/sh
if [ ! -f /db/ffplayout.db ]; then if [ ! -f /db/ffplayout.db ]; then
ffplayout -i -u admin -p admin -m contact@example.com --storage "/tv-media" --playlist "/playlists" --public "/public" --log-path "/logging" --shared ffplayout -i -u admin -p admin -m contact@example.com --storage "/tv-media" --playlists "/playlists" --public "/public" --logs "/logging" --mail-smtp "mail.example.org" --mail-user "admin@example.org" --mail-password "abcd" --mail-starttls
mkdir /tv-media/1
cp -r /00-assets /tv-media/1/
fi fi
/usr/bin/ffplayout -l "0.0.0.0:8787" /usr/bin/ffplayout -l "0.0.0.0:8787"
@ -28,6 +31,8 @@ RUN [[ -f "/tmp/ffplayout-v${FFPLAYOUT_VERSION}_x86_64-unknown-linux-musl.tar.gz
cd /tmp && \ cd /tmp && \
tar xf "ffplayout-v${FFPLAYOUT_VERSION}_x86_64-unknown-linux-musl.tar.gz" && \ tar xf "ffplayout-v${FFPLAYOUT_VERSION}_x86_64-unknown-linux-musl.tar.gz" && \
cp ffplayout /usr/bin/ && \ cp ffplayout /usr/bin/ && \
mkdir /00-assets && \
cp assets/dummy.vtt assets/logo.png assets/DejaVuSans.ttf assets/FONT_LICENSE.txt /00-assets/ && \
rm -rf /tmp/* && \ rm -rf /tmp/* && \
mkdir ${DB} mkdir ${DB}

View File

@ -22,7 +22,7 @@ How to build the image:\
# build default # build default
docker build -t ffplayout-image . docker build -t ffplayout-image .
# build from root folder, to copy local *.rpm package # build from root folder, to copy *.tar.gz with self compiled binary
docker build -f docker/Dockerfile -t ffplayout-image . docker build -f docker/Dockerfile -t ffplayout-image .
# build ffmpeg from source # build ffmpeg from source
@ -45,6 +45,14 @@ docker run -d --name ffplayout -p 8787:8787 ffplayout-image
docker-compose up -d docker-compose up -d
``` ```
For setup mail server settings run:
```
docker exec -it ffplayout ffplayout -i
```
Then restart Container
#### Note from CentOS docker hub page #### Note from CentOS docker hub page
There have been reports that if you're using an Ubuntu host, you will need to add `-v /tmp/$(mktemp -d):/run` to the mount. There have been reports that if you're using an Ubuntu host, you will need to add `-v /tmp/$(mktemp -d):/run` to the mount.

View File

@ -14,7 +14,10 @@ COPY <<-EOT /run.sh
#!/bin/sh #!/bin/sh
if [ ! -f /db/ffplayout.db ]; then if [ ! -f /db/ffplayout.db ]; then
ffplayout -i -u admin -p admin -m contact@example.com --storage "/tv-media" --playlist "/playlists" --public "/public" --log-path "/logging" --shared ffplayout -i -u admin -p admin -m contact@example.com --storage "/tv-media" --playlists "/playlists" --public "/public" --logs "/logging" --mail-smtp "mail.example.org" --mail-user "admin@example.org" --mail-password "abcd" --mail-starttls
mkdir /tv-media/1
cp -r /00-assets /tv-media/1/
fi fi
/usr/bin/ffplayout -l "0.0.0.0:8787" /usr/bin/ffplayout -l "0.0.0.0:8787"
@ -30,6 +33,8 @@ RUN [[ -f "/tmp/ffplayout-v${FFPLAYOUT_VERSION}_x86_64-unknown-linux-musl.tar.gz
cd /tmp && \ cd /tmp && \
tar xf "ffplayout-v${FFPLAYOUT_VERSION}_x86_64-unknown-linux-musl.tar.gz" && \ tar xf "ffplayout-v${FFPLAYOUT_VERSION}_x86_64-unknown-linux-musl.tar.gz" && \
cp ffplayout /usr/bin/ && \ cp ffplayout /usr/bin/ && \
mkdir /00-assets && \
cp assets/dummy.vtt assets/logo.png assets/DejaVuSans.ttf assets/FONT_LICENSE.txt /00-assets/ && \
rm -rf /tmp/* && \ rm -rf /tmp/* && \
mkdir ${DB} mkdir ${DB}

View File

@ -204,7 +204,10 @@ COPY <<-EOT /run.sh
#!/bin/sh #!/bin/sh
if [ ! -f /db/ffplayout.db ]; then if [ ! -f /db/ffplayout.db ]; then
ffplayout -i -u admin -p admin -m contact@example.com --storage "/tv-media" --playlist "/playlists" --public "/public" --log-path "/logging" --shared ffplayout -i -u admin -p admin -m contact@example.com --storage "/tv-media" --playlists "/playlists" --public "/public" --logs "/logging" --mail-smtp "mail.example.org" --mail-user "admin@example.org" --mail-password "abcd" --mail-starttls
mkdir /tv-media/1
cp -r /00-assets /tv-media/1/
fi fi
/usr/bin/ffplayout -l "0.0.0.0:8787" /usr/bin/ffplayout -l "0.0.0.0:8787"
@ -217,6 +220,8 @@ RUN [[ -f "/tmp/ffplayout-v${FFPLAYOUT_VERSION}_x86_64-unknown-linux-musl.tar.gz
cd /tmp && \ cd /tmp && \
tar xf "ffplayout-v${FFPLAYOUT_VERSION}_x86_64-unknown-linux-musl.tar.gz" && \ tar xf "ffplayout-v${FFPLAYOUT_VERSION}_x86_64-unknown-linux-musl.tar.gz" && \
cp ffplayout /usr/bin/ && \ cp ffplayout /usr/bin/ && \
mkdir /00-assets && \
cp assets/dummy.vtt assets/logo.png assets/DejaVuSans.ttf assets/FONT_LICENSE.txt /00-assets/ && \
rm -rf /tmp/* && \ rm -rf /tmp/* && \
mkdir ${DB} mkdir ${DB}

View File

@ -9,7 +9,10 @@ use tokio::task;
use super::models::{AdvancedConfiguration, Configuration}; use super::models::{AdvancedConfiguration, Configuration};
use crate::db::models::{Channel, GlobalSettings, Role, TextPreset, User}; use crate::db::models::{Channel, GlobalSettings, Role, TextPreset, User};
use crate::utils::{advanced_config::AdvancedConfig, config::PlayoutConfig, local_utc_offset}; use crate::utils::{
advanced_config::AdvancedConfig, config::PlayoutConfig, is_running_in_container,
local_utc_offset,
};
pub async fn db_migrate(conn: &Pool<Sqlite>) -> Result<(), Box<dyn std::error::Error>> { pub async fn db_migrate(conn: &Pool<Sqlite>) -> Result<(), Box<dyn std::error::Error>> {
sqlx::migrate!("../migrations").run(conn).await?; sqlx::migrate!("../migrations").run(conn).await?;
@ -20,6 +23,7 @@ pub async fn db_migrate(conn: &Pool<Sqlite>) -> Result<(), Box<dyn std::error::E
.take(80) .take(80)
.map(char::from) .map(char::from)
.collect(); .collect();
let shared = is_running_in_container().await;
let query = "CREATE TRIGGER global_row_count let query = "CREATE TRIGGER global_row_count
BEFORE INSERT ON global BEFORE INSERT ON global
@ -27,9 +31,13 @@ pub async fn db_migrate(conn: &Pool<Sqlite>) -> Result<(), Box<dyn std::error::E
BEGIN BEGIN
SELECT RAISE(FAIL, 'Database is already initialized!'); SELECT RAISE(FAIL, 'Database is already initialized!');
END; END;
INSERT INTO global(secret) VALUES($1);"; INSERT INTO global(secret, shared) VALUES($1, $2);";
sqlx::query(query).bind(secret).execute(conn).await?; sqlx::query(query)
.bind(secret)
.bind(shared)
.execute(conn)
.await?;
} }
Ok(()) Ok(())
@ -46,9 +54,8 @@ pub async fn update_global(
conn: &Pool<Sqlite>, conn: &Pool<Sqlite>,
global: GlobalSettings, global: GlobalSettings,
) -> Result<SqliteQueryResult, sqlx::Error> { ) -> Result<SqliteQueryResult, sqlx::Error> {
let query = let query = "UPDATE global SET logs = $2, playlists = $3, public = $4, storage = $5,
"UPDATE global SET logs = $2, playlists = $3, public = $4, storage = $5, shared = $6, mail_smtp = $6, mail_user = $7, mail_password = $8, mail_starttls = $9 WHERE id = 1";
mail_smtp = $7, mail_user = $8, mail_password = $9, mail_starttls = $10 WHERE id = 1";
sqlx::query(query) sqlx::query(query)
.bind(global.id) .bind(global.id)
@ -56,7 +63,6 @@ pub async fn update_global(
.bind(global.playlists) .bind(global.playlists)
.bind(global.public) .bind(global.public)
.bind(global.storage) .bind(global.storage)
.bind(global.shared)
.bind(global.mail_smtp) .bind(global.mail_smtp)
.bind(global.mail_user) .bind(global.mail_user)
.bind(global.mail_password) .bind(global.mail_password)

View File

@ -71,14 +71,6 @@ pub struct Args {
#[clap(long, env, help_heading = Some("Initial Setup"), help = "Use TLS for system mails")] #[clap(long, env, help_heading = Some("Initial Setup"), help = "Use TLS for system mails")]
pub mail_starttls: bool, pub mail_starttls: bool,
#[clap(
long,
env,
help_heading = Some("Initial Setup"),
help = "Share storage across channels, important for running in Containers"
)]
pub shared: bool,
#[clap(long, env, help_heading = Some("Initial Setup / General"), help = "Logging path")] #[clap(long, env, help_heading = Some("Initial Setup / General"), help = "Logging path")]
pub logs: Option<String>, pub logs: Option<String>,
@ -251,7 +243,6 @@ pub async fn run_args(pool: &Pool<Sqlite>) -> Result<(), i32> {
let mut playlist = String::new(); let mut playlist = String::new();
let mut logging = String::new(); let mut logging = String::new();
let mut public = String::new(); let mut public = String::new();
let mut shared_store = String::new();
let mut mail_smtp = String::new(); let mut mail_smtp = String::new();
let mut mail_user = String::new(); let mut mail_user = String::new();
let mut mail_starttls = String::new(); let mut mail_starttls = String::new();
@ -329,23 +320,6 @@ pub async fn run_args(pool: &Pool<Sqlite>) -> Result<(), i32> {
} }
} }
if args.shared {
global.shared = true;
} else {
print!(
"Shared storage [{}]: ",
if global.shared { "yes" } else { "no" }
);
stdout().flush().unwrap();
stdin()
.read_line(&mut shared_store)
.expect("Did not enter a yes or no?");
if !shared_store.trim().is_empty() {
global.shared = shared_store.trim().to_lowercase().starts_with('y');
}
}
if let Some(smtp) = args.mail_smtp { if let Some(smtp) = args.mail_smtp {
global.mail_smtp = smtp; global.mail_smtp = smtp;
} else { } else {

View File

@ -162,7 +162,6 @@ pub struct Source {
/// Channel Config /// Channel Config
/// ///
/// This we init ones, when ffplayout is starting and use them globally in the hole program. /// This we init ones, when ffplayout is starting and use them globally in the hole program.
#[derive(Debug, Default, Clone, Deserialize, Serialize, TS)] #[derive(Debug, Default, Clone, Deserialize, Serialize, TS)]
#[ts(export, export_to = "playout_config.d.ts")] #[ts(export, export_to = "playout_config.d.ts")]
pub struct PlayoutConfig { pub struct PlayoutConfig {
@ -624,7 +623,7 @@ impl PlayoutConfig {
.unwrap_or_else(|_| panic!("Can't create storage folder: {:#?}", channel.storage)); .unwrap_or_else(|_| panic!("Can't create storage folder: {:#?}", channel.storage));
} }
let mut storage = Storage::new(&config, channel.storage.clone(), global.shared); let mut storage = Storage::new(&config, channel.storage.clone(), channel.shared);
if !channel.playlists.is_dir() { if !channel.playlists.is_dir() {
tokio::fs::create_dir_all(&channel.playlists).await?; tokio::fs::create_dir_all(&channel.playlists).await?;
@ -945,12 +944,6 @@ pub async fn get_config(
} }
} }
if args.shared {
// config.channel.shared could be true already,
// so should not be overridden with false when args.shared is not set
config.channel.shared = true
}
if let Some(volume) = args.volume { if let Some(volume) = args.volume {
config.processing.volume = volume; config.processing.volume = volume;
} }

View File

@ -13,7 +13,7 @@ use log::*;
use path_clean::PathClean; use path_clean::PathClean;
use rand::Rng; use rand::Rng;
use regex::Regex; use regex::Regex;
use tokio::fs; use tokio::{fs, process::Command};
use serde::{ use serde::{
de::{self, Visitor}, de::{self, Visitor},
@ -369,3 +369,19 @@ pub async fn copy_assets(storage_path: &Path) -> Result<(), std::io::Error> {
Ok(()) Ok(())
} }
/// Combined function to check if the program is running inside a container.
/// Returns `true` if running inside a container, otherwise `false`.
pub async fn is_running_in_container() -> bool {
// Check for Docker or Podman specific files
if Path::new("/.dockerenv").exists() || Path::new("/run/.containerenv").exists() {
return true;
}
// Run `systemd-detect-virt -c` to check if we are in a container
if let Ok(output) = Command::new("systemd-detect-virt").arg("-c").output().await {
return output.status.success();
}
false
}

View File

@ -226,7 +226,7 @@ export default {
publicPath: 'Public (HLS) Pfad', publicPath: 'Public (HLS) Pfad',
playlistPath: 'Wiedergabelistenpfad', playlistPath: 'Wiedergabelistenpfad',
storagePath: 'Speicherpfad', storagePath: 'Speicherpfad',
sharedStorage: 'Gemeinsamer Speicher ist aktiviert, verwende denselben Speicherstamm für alle Kanäle!', sharedStorage: 'ffplayout läuft innerhalb eines Containers, verwenden Sie den gleichen Speicherstamm für alle Kanäle!',
}, },
user: { user: {
title: 'Benutzer-Konfiguration', title: 'Benutzer-Konfiguration',

View File

@ -227,7 +227,7 @@ export default {
publicPath: 'Public (HLS) Path', publicPath: 'Public (HLS) Path',
playlistPath: 'Playlist Path', playlistPath: 'Playlist Path',
storagePath: 'Storage Path', storagePath: 'Storage Path',
sharedStorage: 'Shared storage is enabled, use the same storage root for all channels!', sharedStorage: 'ffplayout runs inside a container, use the same storage root for all channels!',
}, },
user: { user: {
title: 'User Configuration', title: 'User Configuration',

View File

@ -226,7 +226,7 @@ export default {
publicPath: 'Public (HLS) Path', publicPath: 'Public (HLS) Path',
playlistPath: 'Playlist Path', playlistPath: 'Playlist Path',
storagePath: 'Storage Path', storagePath: 'Storage Path',
sharedStorage: 'O armazenamento compartilhado está ativado, use a mesma raiz de armazenamento para todos os canais', sharedStorage: 'O ffplayout é executado dentro de um contêiner; use a mesma raiz de armazenamento para todos os canais!',
}, },
user: { user: {
title: 'Configuração de usuário', title: 'Configuração de usuário',

View File

@ -227,7 +227,7 @@ export default {
publicPath: 'Public (HLS) Path', publicPath: 'Public (HLS) Path',
playlistPath: 'Playlist Path', playlistPath: 'Playlist Path',
storagePath: 'Storage Path', storagePath: 'Storage Path',
sharedStorage: 'Общее хранилище включено, используйте один и тот же корень хранилища для всех каналов!', sharedStorage: 'ffplayout работает внутри контейнера, используйте один и тот же корень хранилища для всех каналов!',
}, },
user: { user: {
title: 'Конфигурация пользователя', title: 'Конфигурация пользователя',

File diff suppressed because it is too large Load Diff

View File

@ -27,21 +27,21 @@
"pinia": "^2.2.4", "pinia": "^2.2.4",
"sortablejs-vue3": "^1.2.11", "sortablejs-vue3": "^1.2.11",
"splitpanes": "^3.1.5", "splitpanes": "^3.1.5",
"video.js": "^8.17.4" "video.js": "^8.18.1"
}, },
"devDependencies": { "devDependencies": {
"@nuxt/eslint": "^0.5.7", "@nuxt/eslint": "^0.6.0",
"@nuxtjs/i18n": "^8.5.5", "@nuxtjs/i18n": "^8.5.5",
"@nuxtjs/tailwindcss": "^6.12.1", "@nuxtjs/tailwindcss": "^6.12.2",
"@types/lodash-es": "^4.17.12", "@types/lodash-es": "^4.17.12",
"@types/video.js": "^7.3.58", "@types/video.js": "^7.3.58",
"daisyui": "^4.12.12", "daisyui": "^4.12.13",
"mini-svg-data-uri": "^1.4.4", "mini-svg-data-uri": "^1.4.4",
"postcss": "^8.4.47", "postcss": "^8.4.47",
"postcss-loader": "^8.1.1", "postcss-loader": "^8.1.1",
"sass": "^1.79.4", "sass": "^1.80.2",
"sass-loader": "^16.0.2", "sass-loader": "^16.0.2",
"vue": "^3.5.11", "vue": "^3.5.12",
"vue-router": "^4.4.5" "vue-router": "^4.4.5"
} }
} }

View File

@ -369,10 +369,6 @@ onMounted(async () => {
let config_extensions = configStore.playout.storage.extensions let config_extensions = configStore.playout.storage.extensions
let extra_extensions = configStore.channels[configStore.i].extra_extensions let extra_extensions = configStore.channels[configStore.i].extra_extensions
if (typeof config_extensions === 'string') {
config_extensions = config_extensions.split(',')
}
if (typeof extra_extensions === 'string') { if (typeof extra_extensions === 'string') {
extra_extensions = extra_extensions.split(',') extra_extensions = extra_extensions.split(',')
} }