diff --git a/docker/Dockerfile b/docker/Dockerfile index 2c80bc1c..f4f9c893 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -10,7 +10,7 @@ COPY <<-EOT /run.sh #!/bin/sh if [ ! -f /db/ffplayout.db ]; then - 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 "" --mail-starttls + ffplayout -i -u admin -p admin -m contact@example.com --storage "/tv-media" --playlists "/playlists" --public "/public" --logs "/logging" --smtp-server "mail.example.org" --smtp-user "admin@example.org" --smtp-password "" --smtp-port 465 --smtp-starttls false fi /usr/bin/ffplayout -l "0.0.0.0:8787" diff --git a/docker/nonfree.Dockerfile b/docker/nonfree.Dockerfile index d819f3f1..2d435ee6 100644 --- a/docker/nonfree.Dockerfile +++ b/docker/nonfree.Dockerfile @@ -12,7 +12,7 @@ COPY <<-EOT /run.sh #!/bin/sh if [ ! -f /db/ffplayout.db ]; then - 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 "" --mail-starttls + ffplayout -i -u admin -p admin -m contact@example.com --storage "/tv-media" --playlists "/playlists" --public "/public" --logs "/logging" --smtp-server "mail.example.org" --smtp-user "admin@example.org" --smtp-password "" --smtp-port 465 --smtp-starttls false fi /usr/bin/ffplayout -l "0.0.0.0:8787" diff --git a/docker/nvidia.Dockerfile b/docker/nvidia.Dockerfile index ccad8fbd..65fffcbf 100644 --- a/docker/nvidia.Dockerfile +++ b/docker/nvidia.Dockerfile @@ -200,7 +200,7 @@ COPY <<-EOT /run.sh #!/bin/sh if [ ! -f /db/ffplayout.db ]; then - 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 "" --mail-starttls + ffplayout -i -u admin -p admin -m contact@example.com --storage "/tv-media" --playlists "/playlists" --public "/public" --logs "/logging" --smtp-server "mail.example.org" --smtp-user "admin@example.org" --smtp-password "" --smtp-port 465 --smtp-starttls false fi /usr/bin/ffplayout -l "0.0.0.0:8787" diff --git a/engine/src/api/routes.rs b/engine/src/api/routes.rs index 6d3e07aa..f6ba9106 100644 --- a/engine/src/api/routes.rs +++ b/engine/src/api/routes.rs @@ -668,7 +668,7 @@ async fn add_advanced_config( .await .ok_or(ServiceError::BadRequest("Channel not found".to_string()))?; - handles::insert_advanced_configuration(&pool, *id, data.into_inner()).await?; + handles::insert_advanced_configuration(&pool, *id, None, data.into_inner()).await?; let new_config = get_config(&pool, *id).await?; manager.update_config(new_config).await; diff --git a/engine/src/db/handles.rs b/engine/src/db/handles.rs index 8805c84c..8ce241e1 100644 --- a/engine/src/db/handles.rs +++ b/engine/src/db/handles.rs @@ -9,12 +9,31 @@ use sqlx::{sqlite::SqliteQueryResult, Pool, Row, Sqlite}; use super::models::{AdvancedConfiguration, Configuration}; use crate::db::models::{Channel, GlobalSettings, Role, TextPreset, User}; use crate::utils::{ - advanced_config::AdvancedConfig, + advanced_config::{AdvancedConfig, DecoderConfig, FilterConfig, IngestConfig}, config::PlayoutConfig, errors::{ProcessError, ServiceError}, is_running_in_container, }; +pub const NVIDIA_NAME: &str = "Nvidia"; +pub const NVIDIA_INPUT: &str = + "-thread_queue_size 1024 -hwaccel_device 0 -hwaccel cuvid -hwaccel_output_format cuda"; +pub const NVIDIA_DECODER_OUTPUT: &str = "-c:v h264_nvenc -preset p2 -tune ll -b:v 50000k -minrate 50000k -maxrate 50000k -bufsize 25000k -c:a s302m -strict -2 -sample_fmt s16 -ar 48000 -ac 2"; +pub const NVIDIA_FILTER_DEINTERLACE: &str = "yadif_cuda=0:-1:0"; +pub const NVIDIA_FILTER_SCALE: &str = "scale_cuda={}:{}:format=yuv420p"; +pub const NVIDIA_FILTER_LOGO_SCALE: &str = "null"; +pub const NVIDIA_FILTER_OVERLAY: &str = "overlay_cuda={}:shortest=1"; + +pub const QSV_NAME: &str = "QSV"; +pub const QSV_INPUT: &str = + "-hwaccel qsv -init_hw_device qsv=hw -filter_hw_device hw -hwaccel_output_format qsv"; +pub const QSV_DECODER_OUTPUT: &str = "-c:v mpeg2_qsv -g 1 -b:v 50000k -minrate 50000k -maxrate 50000k -bufsize 25000k -c:a s302m -strict -2 -sample_fmt s16 -ar 48000 -ac 2"; +pub const QSV_FILTER_DEINTERLACE: &str = "deinterlace_qsv"; +pub const QSV_FILTER_FPS: &str = "vpp_qsv=framerate=25"; +pub const QSV_FILTER_SCALE: &str = "scale_qsv={}:{}"; +pub const QSV_FILTER_LOGO_SCALE: &str = "scale_qsv={}"; +pub const QSV_FILTER_OVERLAY: &str = "overlay_qsv={}:shortest=1"; + pub async fn db_migrate(conn: &Pool) -> Result<(), ProcessError> { sqlx::migrate!("../migrations").run(conn).await?; @@ -39,6 +58,61 @@ pub async fn db_migrate(conn: &Pool) -> Result<(), ProcessError> { .bind(shared) .execute(conn) .await?; + + insert_advanced_configuration( + conn, + 1, + Some(1), + AdvancedConfig { + name: Some(NVIDIA_NAME.to_string()), + decoder: DecoderConfig { + input_param: Some(NVIDIA_INPUT.to_string()), + output_param: Some(NVIDIA_DECODER_OUTPUT.to_string()), + ..Default::default() + }, + ingest: IngestConfig { + input_param: Some(NVIDIA_INPUT.to_string()), + ..Default::default() + }, + filter: FilterConfig { + deinterlace: Some(NVIDIA_FILTER_DEINTERLACE.to_string()), + scale: Some(NVIDIA_FILTER_SCALE.to_string()), + overlay_logo_scale: Some(NVIDIA_FILTER_LOGO_SCALE.to_string()), + overlay_logo: Some(NVIDIA_FILTER_OVERLAY.to_string()), + ..Default::default() + }, + ..Default::default() + }, + ) + .await?; + + insert_advanced_configuration( + conn, + 1, + Some(1), + AdvancedConfig { + name: Some(QSV_NAME.to_string()), + decoder: DecoderConfig { + input_param: Some(QSV_INPUT.to_string()), + output_param: Some(QSV_DECODER_OUTPUT.to_string()), + ..Default::default() + }, + ingest: IngestConfig { + input_param: Some(QSV_INPUT.to_string()), + ..Default::default() + }, + filter: FilterConfig { + deinterlace: Some(QSV_FILTER_DEINTERLACE.to_string()), + fps: Some(QSV_FILTER_FPS.to_string()), + scale: Some(QSV_FILTER_SCALE.to_string()), + overlay_logo_scale: Some(QSV_FILTER_LOGO_SCALE.to_string()), + overlay_logo: Some(QSV_FILTER_OVERLAY.to_string()), + ..Default::default() + }, + ..Default::default() + }, + ) + .await?; } Ok(()) @@ -317,8 +391,9 @@ pub async fn update_configuration( pub async fn insert_advanced_configuration( conn: &Pool, channel_id: i32, + adv_id: Option, config: AdvancedConfig, -) -> Result<(), ProcessError> { +) -> Result { const QUERY_INSERT: &str = "INSERT INTO advanced_configurations (channel_id, decoder_input_param, decoder_output_param, encoder_input_param, ingest_input_param, filter_deinterlace, filter_pad_video, filter_fps, filter_scale, filter_set_dar, @@ -362,13 +437,15 @@ pub async fn insert_advanced_configuration( .await? .get("id"); + let a_id = adv_id.unwrap_or(advanced_id); + sqlx::query(QUERY_UPDATE) .bind(channel_id) - .bind(advanced_id) + .bind(a_id) .execute(conn) .await?; - Ok(()) + Ok(advanced_id) } pub async fn update_advanced_configuration( diff --git a/engine/src/utils/channels.rs b/engine/src/utils/channels.rs index 76a433e2..62a844f2 100644 --- a/engine/src/utils/channels.rs +++ b/engine/src/utils/channels.rs @@ -4,10 +4,16 @@ use log::*; use sqlx::{Pool, Sqlite}; use tokio::sync::Mutex; -use crate::db::{handles, models::Channel}; +use crate::db::{ + handles::{self, *}, + models::Channel, +}; use crate::player::controller::{ChannelController, ChannelManager}; use crate::utils::{ - advanced_config::AdvancedConfig, config::get_config, copy_assets, errors::ServiceError, + advanced_config::{AdvancedConfig, DecoderConfig, FilterConfig, IngestConfig}, + config::get_config, + copy_assets, + errors::ServiceError, mail::MailQueue, }; @@ -39,9 +45,10 @@ pub async fn create_channel( handles::new_channel_presets(conn, channel.id).await?; handles::update_channel(conn, channel.id, channel.clone()).await?; - handles::insert_advanced_configuration( + let adv_id = handles::insert_advanced_configuration( conn, channel.id, + None, AdvancedConfig { name: Some("None".to_string()), ..Default::default() @@ -49,6 +56,59 @@ pub async fn create_channel( ) .await?; handles::insert_configuration(conn, channel.id, OUTPUT_PARM).await?; + handles::insert_advanced_configuration( + conn, + channel.id, + Some(adv_id), + AdvancedConfig { + name: Some(NVIDIA_NAME.to_string()), + decoder: DecoderConfig { + input_param: Some(NVIDIA_INPUT.to_string()), + output_param: Some(NVIDIA_DECODER_OUTPUT.to_string()), + ..Default::default() + }, + ingest: IngestConfig { + input_param: Some(NVIDIA_INPUT.to_string()), + ..Default::default() + }, + filter: FilterConfig { + deinterlace: Some(NVIDIA_FILTER_DEINTERLACE.to_string()), + scale: Some(NVIDIA_FILTER_SCALE.to_string()), + overlay_logo_scale: Some(NVIDIA_FILTER_LOGO_SCALE.to_string()), + overlay_logo: Some(NVIDIA_FILTER_OVERLAY.to_string()), + ..Default::default() + }, + ..Default::default() + }, + ) + .await?; + handles::insert_advanced_configuration( + conn, + channel.id, + Some(adv_id), + AdvancedConfig { + name: Some(QSV_NAME.to_string()), + decoder: DecoderConfig { + input_param: Some(QSV_INPUT.to_string()), + output_param: Some(QSV_DECODER_OUTPUT.to_string()), + ..Default::default() + }, + ingest: IngestConfig { + input_param: Some(QSV_INPUT.to_string()), + ..Default::default() + }, + filter: FilterConfig { + deinterlace: Some(QSV_FILTER_DEINTERLACE.to_string()), + fps: Some(QSV_FILTER_FPS.to_string()), + scale: Some(QSV_FILTER_SCALE.to_string()), + overlay_logo_scale: Some(QSV_FILTER_LOGO_SCALE.to_string()), + overlay_logo: Some(QSV_FILTER_OVERLAY.to_string()), + ..Default::default() + }, + ..Default::default() + }, + ) + .await?; let config = get_config(conn, channel.id).await?; diff --git a/frontend/components/ConfigChannel.vue b/frontend/components/ConfigChannel.vue index 87604987..837ad180 100644 --- a/frontend/components/ConfigChannel.vue +++ b/frontend/components/ConfigChannel.vue @@ -14,6 +14,7 @@ @@ -73,6 +77,7 @@ @@ -85,6 +90,7 @@ diff --git a/migrations/00004_extend_configs.sql b/migrations/00004_extend_configs.sql index 03d4e6a0..8186b2d4 100644 --- a/migrations/00004_extend_configs.sql +++ b/migrations/00004_extend_configs.sql @@ -10,55 +10,3 @@ DROP filter_pad_scale_h; ALTER TABLE advanced_configurations ADD name TEXT; UPDATE advanced_configurations SET name = 'None'; - -INSERT INTO - advanced_configurations ( - channel_id, - decoder_input_param, - decoder_output_param, - ingest_input_param, - filter_deinterlace, - filter_scale, - filter_overlay_logo_scale, - filter_overlay_logo, - name - ) -VALUES - ( - 1, - '-thread_queue_size 1024 -hwaccel_device 0 -hwaccel cuvid -hwaccel_output_format cuda', - '-c:v h264_nvenc -preset p2 -tune ll -b:v 50000k -minrate 50000k -maxrate 50000k -bufsize 25000k -c:a s302m -strict -2 -sample_fmt s16 -ar 48000 -ac 2', - '-thread_queue_size 1024 -hwaccel_device 0 -hwaccel cuvid -hwaccel_output_format cuda', - 'yadif_cuda=0:-1:0', - 'scale_cuda={}:{}:format=yuv420p', - 'null', - 'overlay_cuda={}:shortest=1', - 'Nvidia' - ); - -INSERT INTO - advanced_configurations ( - channel_id, - decoder_input_param, - decoder_output_param, - ingest_input_param, - filter_deinterlace, - filter_fps, - filter_scale, - filter_overlay_logo_scale, - filter_overlay_logo, - name - ) -VALUES - ( - 1, - '-hwaccel qsv -init_hw_device qsv=hw -filter_hw_device hw -hwaccel_output_format qsv', - '-c:v mpeg2_qsv -g 1 -b:v 50000k -minrate 50000k -maxrate 50000k -bufsize 25000k -c:a s302m -strict -2 -sample_fmt s16 -ar 48000 -ac 2', - '-hwaccel qsv -init_hw_device qsv=hw -filter_hw_device hw -hwaccel_output_format qsv', - 'deinterlace_qsv', - 'vpp_qsv=framerate=25', - 'scale_qsv={}:{}', - 'scale_qsv={}', - 'overlay_qsv={}:shortest=1', - 'QSV' - );