diff --git a/Cargo.lock b/Cargo.lock
index b6c9019..0b909ff 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -285,9 +285,9 @@ dependencies = [
[[package]]
name = "async-signal"
-version = "0.2.7"
+version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "329972aa325176e89114919f2a80fdae4f4c040f66a370b1a1159c6c0f94e7aa"
+checksum = "794f185324c2f00e771cd9f1ae8b5ac68be2ca7abb129a87afd6e86d228bc54d"
dependencies = [
"async-io 2.3.3",
"async-lock 3.4.0",
@@ -432,6 +432,7 @@ dependencies = [
"cpal",
"dark-light",
"dirs",
+ "ffmpeg-sidecar",
"filename",
"fluent-bundle",
"gdk-pixbuf 0.9.0",
@@ -484,7 +485,7 @@ dependencies = [
[[package]]
name = "cairo-rs"
version = "0.20.0"
-source = "git+https://github.com/gtk-rs/gtk-rs-core?branch=master#7cd06421c5027e2c1b4cc657529e6acd8bac1ea3"
+source = "git+https://github.com/gtk-rs/gtk-rs-core?branch=master#0a0d3166157123035acc396c00ce8816011b1697"
dependencies = [
"bitflags 2.5.0",
"cairo-sys-rs 0.20.0",
@@ -507,7 +508,7 @@ dependencies = [
[[package]]
name = "cairo-sys-rs"
version = "0.20.0"
-source = "git+https://github.com/gtk-rs/gtk-rs-core?branch=master#7cd06421c5027e2c1b4cc657529e6acd8bac1ea3"
+source = "git+https://github.com/gtk-rs/gtk-rs-core?branch=master#0a0d3166157123035acc396c00ce8816011b1697"
dependencies = [
"glib-sys 0.20.0",
"libc",
@@ -889,6 +890,15 @@ version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a"
+[[package]]
+name = "ffmpeg-sidecar"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bec830aba6cd3da7621c58e8f06727e3b750e8383bcd934d789f2b9c3c4ea595"
+dependencies = [
+ "anyhow",
+]
+
[[package]]
name = "field-offset"
version = "0.3.6"
@@ -1091,7 +1101,7 @@ dependencies = [
[[package]]
name = "gdk-pixbuf"
version = "0.20.0"
-source = "git+https://github.com/gtk-rs/gtk-rs-core?branch=master#7cd06421c5027e2c1b4cc657529e6acd8bac1ea3"
+source = "git+https://github.com/gtk-rs/gtk-rs-core?branch=master#0a0d3166157123035acc396c00ce8816011b1697"
dependencies = [
"gdk-pixbuf-sys 0.20.0",
"gio 0.20.0",
@@ -1128,7 +1138,7 @@ dependencies = [
[[package]]
name = "gdk-pixbuf-sys"
version = "0.20.0"
-source = "git+https://github.com/gtk-rs/gtk-rs-core?branch=master#7cd06421c5027e2c1b4cc657529e6acd8bac1ea3"
+source = "git+https://github.com/gtk-rs/gtk-rs-core?branch=master#0a0d3166157123035acc396c00ce8816011b1697"
dependencies = [
"gio-sys 0.20.0",
"glib-sys 0.20.0",
@@ -1173,7 +1183,7 @@ dependencies = [
[[package]]
name = "gdk4"
version = "0.9.0"
-source = "git+https://github.com/gtk-rs/gtk4-rs.git#32e7155cd32bd5c27e1847c7e38aae825642043a"
+source = "git+https://github.com/gtk-rs/gtk4-rs.git#d1c8a6fedad4d21dfbdb09abe607bf1875cada7e"
dependencies = [
"cairo-rs 0.20.0",
"gdk-pixbuf 0.20.0",
@@ -1204,7 +1214,7 @@ dependencies = [
[[package]]
name = "gdk4-sys"
version = "0.9.0"
-source = "git+https://github.com/gtk-rs/gtk4-rs.git#32e7155cd32bd5c27e1847c7e38aae825642043a"
+source = "git+https://github.com/gtk-rs/gtk4-rs.git#d1c8a6fedad4d21dfbdb09abe607bf1875cada7e"
dependencies = [
"cairo-sys-rs 0.20.0",
"gdk-pixbuf-sys 0.20.0",
@@ -1279,7 +1289,7 @@ dependencies = [
[[package]]
name = "gio"
version = "0.20.0"
-source = "git+https://github.com/gtk-rs/gtk-rs-core?branch=master#7cd06421c5027e2c1b4cc657529e6acd8bac1ea3"
+source = "git+https://github.com/gtk-rs/gtk-rs-core?branch=master#0a0d3166157123035acc396c00ce8816011b1697"
dependencies = [
"futures-channel",
"futures-core",
@@ -1335,7 +1345,7 @@ dependencies = [
[[package]]
name = "gio-sys"
version = "0.20.0"
-source = "git+https://github.com/gtk-rs/gtk-rs-core?branch=master#7cd06421c5027e2c1b4cc657529e6acd8bac1ea3"
+source = "git+https://github.com/gtk-rs/gtk-rs-core?branch=master#0a0d3166157123035acc396c00ce8816011b1697"
dependencies = [
"glib-sys 0.20.0",
"gobject-sys 0.20.0",
@@ -1409,7 +1419,7 @@ dependencies = [
[[package]]
name = "glib"
version = "0.20.0"
-source = "git+https://github.com/gtk-rs/gtk-rs-core?branch=master#7cd06421c5027e2c1b4cc657529e6acd8bac1ea3"
+source = "git+https://github.com/gtk-rs/gtk-rs-core?branch=master#0a0d3166157123035acc396c00ce8816011b1697"
dependencies = [
"bitflags 2.5.0",
"futures-channel",
@@ -1476,7 +1486,7 @@ dependencies = [
[[package]]
name = "glib-macros"
version = "0.20.0"
-source = "git+https://github.com/gtk-rs/gtk-rs-core?branch=master#7cd06421c5027e2c1b4cc657529e6acd8bac1ea3"
+source = "git+https://github.com/gtk-rs/gtk-rs-core?branch=master#0a0d3166157123035acc396c00ce8816011b1697"
dependencies = [
"heck 0.5.0",
"proc-macro-crate 3.1.0",
@@ -1518,7 +1528,7 @@ dependencies = [
[[package]]
name = "glib-sys"
version = "0.20.0"
-source = "git+https://github.com/gtk-rs/gtk-rs-core?branch=master#7cd06421c5027e2c1b4cc657529e6acd8bac1ea3"
+source = "git+https://github.com/gtk-rs/gtk-rs-core?branch=master#0a0d3166157123035acc396c00ce8816011b1697"
dependencies = [
"libc",
"system-deps 6.2.2",
@@ -1578,7 +1588,7 @@ dependencies = [
[[package]]
name = "gobject-sys"
version = "0.20.0"
-source = "git+https://github.com/gtk-rs/gtk-rs-core?branch=master#7cd06421c5027e2c1b4cc657529e6acd8bac1ea3"
+source = "git+https://github.com/gtk-rs/gtk-rs-core?branch=master#0a0d3166157123035acc396c00ce8816011b1697"
dependencies = [
"glib-sys 0.20.0",
"libc",
@@ -2308,7 +2318,7 @@ dependencies = [
[[package]]
name = "pango"
version = "0.20.0"
-source = "git+https://github.com/gtk-rs/gtk-rs-core?branch=master#7cd06421c5027e2c1b4cc657529e6acd8bac1ea3"
+source = "git+https://github.com/gtk-rs/gtk-rs-core?branch=master#0a0d3166157123035acc396c00ce8816011b1697"
dependencies = [
"gio 0.20.0",
"glib 0.20.0",
@@ -2331,7 +2341,7 @@ dependencies = [
[[package]]
name = "pango-sys"
version = "0.20.0"
-source = "git+https://github.com/gtk-rs/gtk-rs-core?branch=master#7cd06421c5027e2c1b4cc657529e6acd8bac1ea3"
+source = "git+https://github.com/gtk-rs/gtk-rs-core?branch=master#0a0d3166157123035acc396c00ce8816011b1697"
dependencies = [
"glib-sys 0.20.0",
"gobject-sys 0.20.0",
@@ -2551,9 +2561,9 @@ dependencies = [
[[package]]
name = "regex"
-version = "1.10.4"
+version = "1.10.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c"
+checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f"
dependencies = [
"aho-corasick",
"memchr",
@@ -2563,9 +2573,9 @@ dependencies = [
[[package]]
name = "regex-automata"
-version = "0.4.6"
+version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea"
+checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df"
dependencies = [
"aho-corasick",
"memchr",
@@ -2574,9 +2584,9 @@ dependencies = [
[[package]]
name = "regex-syntax"
-version = "0.8.3"
+version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56"
+checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b"
[[package]]
name = "rust-ini"
@@ -3475,12 +3485,12 @@ dependencies = [
[[package]]
name = "xdg-home"
-version = "1.1.0"
+version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "21e5a325c3cb8398ad6cf859c1135b25dd29e186679cf2da7581d9679f63b38e"
+checksum = "ca91dcf8f93db085f3a0a29358cd0b9d670915468f4290e8b85d118a34211ab8"
dependencies = [
"libc",
- "winapi",
+ "windows-sys 0.52.0",
]
[[package]]
diff --git a/Cargo.toml b/Cargo.toml
index 79ec0f4..13dc5a3 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -11,8 +11,9 @@ chrono = "0.4.19"
cpal = "0.15.3"
dark-light = "1.0.0"
dirs = "4.0.0"
-fluent-bundle = "0.15.3"
+ffmpeg-sidecar = "1.1.0"
filename = "0.1.1"
+fluent-bundle = "0.15.3"
gdk = { git = "https://github.com/gtk-rs/gtk4-rs.git", package = "gdk4"}
gdk-pixbuf = "0.9.0"
gio = { version = "0.15.0" }
diff --git a/interfaces/main.ui b/interfaces/main.ui
index f693eb7..e807bff 100644
--- a/interfaces/main.ui
+++ b/interfaces/main.ui
@@ -15,17 +15,12 @@
-
@@ -403,6 +398,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
@@ -502,7 +548,7 @@
True
1
- 1
+ 2
@@ -515,7 +561,7 @@
label
0
- 1
+ 2
diff --git a/locales/ar.ftl b/locales/ar.ftl
index 0975019..24b3e5e 100644
--- a/locales/ar.ftl
+++ b/locales/ar.ftl
@@ -102,12 +102,18 @@ license =
لمزيد تفاصيل راجع رخصة جنو العمومية. إن لم تكن حصلت على نسخة من رخصة جنو العمومية مع المسجل الأزرق فانظر { license-website }.
+# Quality label
+quality = الجودة:
+
# Recording button
record = سجل
# Record audio label
record-audio = تسجيل الصوت
+# Record speaker label
+record-speaker = تسجيل المكبر
+
# Record video label
record-video = تسجيل الصورة
@@ -140,8 +146,10 @@ format-tooltip = لاختيار صيغة الخَرج
frames-tooltip = عدد الإطارات في الثانية
hide-tooltip = لإخفاء نافذة المسجل الأزرق عند بدء التسجيل
mouse-tooltip = يظهر مؤشر الفأرة عند التسجيل
+quality-tooltip = جودة التسجيل (CRF)
record-tooltip = يبدأ تسجيل الشاشة
screen-tooltip = يحدد الشاشة ليسجلها
+speaker-tooltip = تسجيل صوت المكبر
stop-tooltip = وقف تسجيل الشاشة
video-tooltip = يسجل الشاشة
wayland-tooltip = غير مدعوم في وايلاند
diff --git a/locales/ar_YE.ftl b/locales/ar_YE.ftl
index 0975019..24b3e5e 100644
--- a/locales/ar_YE.ftl
+++ b/locales/ar_YE.ftl
@@ -102,12 +102,18 @@ license =
لمزيد تفاصيل راجع رخصة جنو العمومية. إن لم تكن حصلت على نسخة من رخصة جنو العمومية مع المسجل الأزرق فانظر { license-website }.
+# Quality label
+quality = الجودة:
+
# Recording button
record = سجل
# Record audio label
record-audio = تسجيل الصوت
+# Record speaker label
+record-speaker = تسجيل المكبر
+
# Record video label
record-video = تسجيل الصورة
@@ -140,8 +146,10 @@ format-tooltip = لاختيار صيغة الخَرج
frames-tooltip = عدد الإطارات في الثانية
hide-tooltip = لإخفاء نافذة المسجل الأزرق عند بدء التسجيل
mouse-tooltip = يظهر مؤشر الفأرة عند التسجيل
+quality-tooltip = جودة التسجيل (CRF)
record-tooltip = يبدأ تسجيل الشاشة
screen-tooltip = يحدد الشاشة ليسجلها
+speaker-tooltip = تسجيل صوت المكبر
stop-tooltip = وقف تسجيل الشاشة
video-tooltip = يسجل الشاشة
wayland-tooltip = غير مدعوم في وايلاند
diff --git a/locales/en.ftl b/locales/en.ftl
index f758083..c0f51ba 100644
--- a/locales/en.ftl
+++ b/locales/en.ftl
@@ -99,12 +99,18 @@ license =
Blue Recorder is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Blue Recorder. If not, see { license-website }.
+# Quality label
+quality = Quality:
+
# Recording button
record = Record
# Record audio label
record-audio = Record Audio
+# Record speaker label
+record-speaker = Record Speaker
+
# Record video label
record-video = Record Video
@@ -132,13 +138,15 @@ audio-source-tooltip = Select audio source
audio-tooltip = Audio recording
delay-tooltip = Delay time before starting record
folder-tooltip = Select storage location
-follow-mouse-tooltip = Highlight Mouse
+follow-mouse-tooltip = Highlight mouse
format-tooltip = Select file format
frames-tooltip = Frames rate
hide-tooltip = Hide window when start recording
mouse-tooltip = Mouse appears in video recording
+quality-tooltip = Video quality (CRF)
record-tooltip = Start screen record
screen-tooltip = Select screen to record
+speaker-tooltip = Speakr sound recording
stop-tooltip = Stop screen recording
video-tooltip = Video recording
wayland-tooltip = Not supported in Wayland
diff --git a/locales/en_US.ftl b/locales/en_US.ftl
index f758083..c0f51ba 100644
--- a/locales/en_US.ftl
+++ b/locales/en_US.ftl
@@ -99,12 +99,18 @@ license =
Blue Recorder is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Blue Recorder. If not, see { license-website }.
+# Quality label
+quality = Quality:
+
# Recording button
record = Record
# Record audio label
record-audio = Record Audio
+# Record speaker label
+record-speaker = Record Speaker
+
# Record video label
record-video = Record Video
@@ -132,13 +138,15 @@ audio-source-tooltip = Select audio source
audio-tooltip = Audio recording
delay-tooltip = Delay time before starting record
folder-tooltip = Select storage location
-follow-mouse-tooltip = Highlight Mouse
+follow-mouse-tooltip = Highlight mouse
format-tooltip = Select file format
frames-tooltip = Frames rate
hide-tooltip = Hide window when start recording
mouse-tooltip = Mouse appears in video recording
+quality-tooltip = Video quality (CRF)
record-tooltip = Start screen record
screen-tooltip = Select screen to record
+speaker-tooltip = Speakr sound recording
stop-tooltip = Stop screen recording
video-tooltip = Video recording
wayland-tooltip = Not supported in Wayland
diff --git a/src/config_management.rs b/src/config_management.rs
index bc81d18..49eada4 100755
--- a/src/config_management.rs
+++ b/src/config_management.rs
@@ -29,6 +29,8 @@ pub fn initialize() -> PathBuf {
fn default() {
set("default", "frame", "60");
set("default", "delay", "0");
+ set("default", "format", "0");
+ set("default", "quality", get_quality(&self::get("default", "format")));
set(
"default",
"folder",
@@ -54,6 +56,7 @@ fn default() {
set("default", "mousecheck", "1");
set("default", "followmousecheck", "0");
set("default", "hidecheck", "0");
+ set("default", "speakercheck", "0");
}
fn merge_previous_version() -> Option {
@@ -125,3 +128,17 @@ pub fn folder_icon(folder_chooser_name: Option<&str>) -> &str {
}
}
}
+
+pub fn get_quality(format: &str) -> &str {
+ let crf = match format {
+ "0" => "23",
+ "1" => "23",
+ "2" => "10.0",
+ "3" => "23",
+ "4" => "23",
+ "5" => "23",
+ "6" => "23.0",
+ _=> "23", // Default value
+ };
+ crf
+}
diff --git a/src/ffmpeg_interface.rs b/src/ffmpeg_interface.rs
index 91227b1..8c8e73b 100644
--- a/src/ffmpeg_interface.rs
+++ b/src/ffmpeg_interface.rs
@@ -2,12 +2,14 @@ extern crate subprocess;
use crate::utils::{is_snap, is_wayland};
use crate::wayland_record::{CursorModeTypes, RecordTypes, WaylandRecorder};
use chrono::prelude::*;
+use ffmpeg_sidecar::child::FfmpegChild;
+use ffmpeg_sidecar::command::FfmpegCommand;
use gtk::{prelude::*, ResponseType};
use gtk::{ButtonsType, DialogFlags, MessageDialog, MessageType};
use gtk::{CheckButton, ComboBoxText, Entry, FileChooserNative, SpinButton, Window};
use std::cell::RefCell;
use std::path::PathBuf;
-use std::process::{Child, Command};
+use std::process::Command;
use std::rc::Rc;
use std::sync::mpsc::Sender;
use std::thread::sleep;
@@ -26,8 +28,8 @@ pub struct Ffmpeg {
pub record_frames: SpinButton,
pub record_delay: SpinButton,
pub command: Entry,
- pub video_process: Option>>,
- pub audio_process: Option>>,
+ pub video_process: Option>>,
+ pub audio_process: Option>>,
pub saved_filename: Option,
pub unbound: Option>,
pub window: Window,
@@ -36,6 +38,7 @@ pub struct Ffmpeg {
pub main_context: gtk::glib::MainContext,
pub temp_video_filename: String,
pub bundle: String,
+ pub record_quality: SpinButton,
}
impl Ffmpeg {
@@ -82,27 +85,17 @@ impl Ffmpeg {
}
if self.record_video.is_active() && !is_wayland() {
- let mut ffmpeg_command: Command = Command::new("ffmpeg");
+ let mut ffmpeg_command = FfmpegCommand::new();
// record video with specified width and hight
- ffmpeg_command.args([
- "-video_size",
- format!("{}x{}", width, height).as_str(),
- "-framerate",
- self.record_frames.value().to_string().as_str(),
- "-f",
- "x11grab",
- "-i",
- format!(
- "{}+{},{}",
- std::env::var("DISPLAY")
- .unwrap_or_else(|_| ":0".to_string())
- .as_str(),
- x,
- y
- )
- .as_str(),
- ]);
+ ffmpeg_command.size(width.into(), height.into())
+ .rate(self.record_frames.value() as f32)
+ .format("x11grab")
+ .input(format!("{}+{},{}", std::env::var("DISPLAY").unwrap_or_else(|_| ":0".to_string())
+ .as_str(),
+ x,
+ y
+ ));
// if show mouse switch is enabled, draw the mouse to video
ffmpeg_command.arg("-draw_mouse");
@@ -123,9 +116,8 @@ impl Ffmpeg {
self.filename.2.active_id().unwrap()
);
+ ffmpeg_command.crf(self.record_quality.value() as u32);
ffmpeg_command.args([
- "-crf",
- "1",
{
if self.record_audio.is_active() {
video_filename.as_str()
@@ -133,8 +125,8 @@ impl Ffmpeg {
self.saved_filename.as_ref().unwrap()
}
},
- "-y",
]);
+ ffmpeg_command.overwrite();
// sleep for delay
sleep(Duration::from_secs(self.record_delay.value() as u64));
@@ -171,18 +163,15 @@ impl Ffmpeg {
}
if self.record_audio.is_active() {
- let mut ffmpeg_command = Command::new("ffmpeg");
- ffmpeg_command.arg("-f");
- ffmpeg_command.arg("pulse");
- ffmpeg_command.arg("-i");
- ffmpeg_command.arg(&self.audio_id.active_id().unwrap());
- ffmpeg_command.arg("-f");
- ffmpeg_command.arg("ogg");
+ let mut ffmpeg_command = FfmpegCommand::new();
+ ffmpeg_command.format("pulse")
+ .input(&self.audio_id.active_id().unwrap())
+ .format("ogg");
ffmpeg_command.arg(format!(
"{}.temp.audio",
self.saved_filename.as_ref().unwrap()
));
- ffmpeg_command.arg("-y");
+ ffmpeg_command.overwrite();
self.audio_process = Some(Rc::new(RefCell::new(ffmpeg_command.spawn().unwrap())));
}
@@ -192,19 +181,11 @@ impl Ffmpeg {
pub fn stop_record(&mut self) {
// kill the process to stop recording
if self.video_process.is_some() {
- Command::new("kill")
- .arg(format!(
- "{}",
- self.video_process.clone().unwrap().borrow_mut().id()
- ))
- .output()
- .unwrap();
-
self.video_process
.clone()
.unwrap()
.borrow_mut()
- .wait()
+ .quit()
.unwrap();
println!("video killed");
@@ -213,20 +194,13 @@ impl Ffmpeg {
}
if self.audio_process.is_some() {
- Command::new("kill")
- .arg(format!(
- "{}",
- self.audio_process.clone().unwrap().borrow_mut().id()
- ))
- .output()
- .unwrap();
-
self.audio_process
.clone()
.unwrap()
.borrow_mut()
- .wait()
+ .quit()
.unwrap();
+
println!("audio killed");
}
@@ -252,20 +226,15 @@ impl Ffmpeg {
if is_video_record {
if is_wayland() {
// convert webm to specified format
- Command::new("ffmpeg")
- .args([
- "-i",
- self.temp_video_filename
- .as_str(),
- "-crf",
- "23", // default quality
- "-c:a",
- self.filename.2.active_id().unwrap().as_str(),
- self.saved_filename.as_ref().unwrap(),
- "-y",
- ])
- .output()
- .unwrap();
+ let mut ffmpeg_command = FfmpegCommand::new();
+ ffmpeg_command.input(self.temp_video_filename.as_str())
+ .crf(self.record_quality.value() as u32)
+ .args([
+ "-c:a",
+ self.filename.2.active_id().unwrap().as_str(),
+ self.saved_filename.as_ref().unwrap(),
+ ]).overwrite().spawn()
+ .unwrap().wait().unwrap();
} else {
let mut move_command = Command::new("mv");
move_command.args([
@@ -281,23 +250,20 @@ impl Ffmpeg {
// if audio record, then merge video and audio
if is_audio_record {
- Command::new("ffmpeg")
- .args([
- "-i",
- video_filename.as_str(),
- "-f",
- "ogg",
- "-i",
- audio_filename.as_str(),
- "-crf",
- "23", // default quality
- "-c:a",
- "aac",
- self.saved_filename.as_ref().unwrap(),
- "-y",
- ])
- .output()
- .expect("failed to merge video and audio");
+ FfmpegCommand::new().input(video_filename.as_str())
+ .format("ogg")
+ .input(audio_filename.as_str())
+ .crf(self.record_quality.value() as u32)
+ .args([
+ "-c:a",
+ "aac",
+ self.saved_filename.as_ref().unwrap(),
+ ])
+ .overwrite()
+ .spawn()
+ .unwrap()
+ .wait()
+ .expect("failed to merge video and audio");
std::fs::remove_file(audio_filename).unwrap();
}
@@ -306,16 +272,13 @@ impl Ffmpeg {
}
// if only audio is recording then convert it to chosen format
else if is_audio_record {
- Command::new("ffmpeg")
- .args([
- "-f",
- "ogg",
- "-i",
- audio_filename.as_str(),
- self.saved_filename.as_ref().unwrap(),
- ])
- .output()
- .expect("failed convert audio to video");
+ let mut ffmpeg_command = FfmpegCommand::new();
+ ffmpeg_command.format("ogg").input(audio_filename.as_str()).arg(
+ self.saved_filename.as_ref().unwrap(),
+ ).spawn()
+ .unwrap()
+ .wait()
+ .expect("failed convert audio to video");
std::fs::remove_file(audio_filename).unwrap();
}
diff --git a/src/main.rs b/src/main.rs
index 66a3c61..4a4b13e 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -81,7 +81,6 @@ pub fn build_ui(application: &Application) {
config_management::initialize();
// Get Objects from UI
- let main_window: Window = builder.object("main_window").unwrap();
let area_apply_label: Label = builder.object("area_apply").unwrap();
let area_chooser_window: Window = builder.object("area_chooser_window").unwrap();
let area_grab_button: ToggleButton = builder.object("area_grab_button").unwrap();
@@ -110,14 +109,18 @@ pub fn build_ui(application: &Application) {
let frames_label: Label = builder.object("frames_label").unwrap();
let frames_spin: SpinButton = builder.object("frames").unwrap();
let hide_switch: CheckButton = builder.object("hideswitch").unwrap();
+ let main_window: Window = builder.object("main_window").unwrap();
let mouse_switch: CheckButton = builder.object("mouseswitch").unwrap();
let play_button: Button = builder.object("playbutton").unwrap();
+ let quality_label: Label = builder.object("quality_label").unwrap();
+ let quality_spin: SpinButton = builder.object("quality").unwrap();
let record_button: Button = builder.object("recordbutton").unwrap();
let record_label: Label = builder.object("record_label").unwrap();
let record_time_label: Label = builder.object("record_time_label").unwrap();
let screen_grab_button: ToggleButton = builder.object("screen_grab_button").unwrap();
let screen_grab_icon: Image = builder.object("screen_grab_icon").unwrap();
let screen_grab_label: Label = builder.object("screen_grab_label").unwrap();
+ let speaker_switch: CheckButton = builder.object("speakerswitch").unwrap();
let stop_button: Button = builder.object("stopbutton").unwrap();
let stop_label: Label = builder.object("stop_label").unwrap();
let video_switch: CheckButton = builder.object("videoswitch").unwrap();
@@ -133,10 +136,6 @@ pub fn build_ui(application: &Application) {
area_chooser_window.set_title(Some(&bundle.format_pattern(bundle.get_message("area-chooser").unwrap()
.value().unwrap(), None, &mut vec![]).to_string())); // Title is hidden
- // disable interaction with main window
- // main_window.set_can_focus(false);
- // main_window.set_can_target(false);
-
// Hide stop & play buttons
stop_button.hide();
play_button.hide();
@@ -169,7 +168,7 @@ pub fn build_ui(application: &Application) {
filename_entry.set_text(&config_management::get("default", "filename"));
command_entry.set_text(&config_management::get("default", "command"));
- // CheckBox
+ // Format combobox
format_chooser_combobox.append(Some("mp4"), &bundle.format_pattern(bundle.get_message("mp4-format").unwrap()
.value().unwrap(), None, &mut vec![]).to_string());
format_chooser_combobox.append(
@@ -187,39 +186,13 @@ pub fn build_ui(application: &Application) {
.value().unwrap(), None, &mut vec![]).to_string());
format_chooser_combobox.append(Some("nut"), &bundle.format_pattern(bundle.get_message("nut-format").unwrap()
.value().unwrap(), None, &mut vec![]).to_string());
- format_chooser_combobox.set_active(Some(0));
+ //format_chooser_combobox.set_active(Some(config_management::get("default", "format").parse::().unwrap()));
// Get audio sources
let input_device = host_audio_device.input_devices().unwrap();
let sources_descriptions: Vec = input_device
.filter_map(|device| device.name().ok())
.collect();
- /*let sources_descriptions: Vec = {
- let list_sources_child = Command::new("pactl")
- .args(&["list", "sources"])
- .stdout(Stdio::piped())
- .spawn();
- let sources_descriptions = String::from_utf8(if let Ok(..) = list_sources_child {
- Command::new("grep")
- .args(&["-e", "device.description"])
- .stdin(list_sources_child.unwrap().stdout.take().unwrap())
- .output()
- .unwrap()
- .stdout
- } else {
- Vec::new()
- })
- .unwrap();
- sources_descriptions
- .split('\n')
- .map(|s| {
- s.trim()
- .replace("device.description = ", "")
- .replace('\"', "")
- })
- .filter(|s| !s.is_empty())
- .collect()
- };*/
audio_source_combobox.append(Some("default"), &bundle.format_pattern(bundle.get_message("audio-input").unwrap()
.value().unwrap(), None, &mut vec![]).to_string());
@@ -249,11 +222,16 @@ pub fn build_ui(application: &Application) {
.value().unwrap(), None, &mut vec![]).to_string()));
hide_switch.set_label(Some(&bundle.format_pattern(bundle.get_message("auto-hide").unwrap()
.value().unwrap(), None, &mut vec![]).to_string()));
+ speaker_switch.set_tooltip_text(Some(&bundle.format_pattern(bundle.get_message("speaker-tooltip").unwrap()
+ .value().unwrap(), None, &mut vec![]).to_string()));
+ speaker_switch.set_label(Some(&bundle.format_pattern(bundle.get_message("record-speaker").unwrap()
+ .value().unwrap(), None, &mut vec![]).to_string()));
video_switch.set_active(config_management::get_bool("default", "videocheck"));
audio_switch.set_active(config_management::get_bool("default", "audiocheck"));
mouse_switch.set_active(config_management::get_bool("default", "mousecheck"));
follow_mouse_switch.set_active(config_management::get_bool("default", "followmousecheck"));
hide_switch.set_active(config_management::get_bool("default", "hidecheck"));
+ speaker_switch.set_active(config_management::get_bool("default", "speakercheck"));
let _video_switch = video_switch.clone();
let _audio_switch = audio_switch.clone();
@@ -295,6 +273,9 @@ pub fn build_ui(application: &Application) {
hide_switch.connect_toggled(|switch: &CheckButton| {
config_management::set_bool("default", "hidecheck", switch.is_active());
});
+ speaker_switch.connect_toggled(|switch: &CheckButton| {
+ config_management::set_bool("default", "speakercheck", switch.is_active());
+ });
match dark_light::detect() {
// Dark mode
@@ -414,17 +395,43 @@ pub fn build_ui(application: &Application) {
.value().unwrap(), None, &mut vec![]).to_string()));
delay_spin.set_tooltip_text(Some(&bundle.format_pattern(bundle.get_message("delay-tooltip").unwrap()
.value().unwrap(), None, &mut vec![]).to_string()));
+ quality_spin.set_tooltip_text(Some(&bundle.format_pattern(bundle.get_message("quality-tooltip").unwrap()
+ .value().unwrap(), None, &mut vec![]).to_string()));
frames_spin.set_value(
config_management::get("default", "frame")
.parse::()
.unwrap(),
);
-
delay_spin.set_value(
config_management::get("default", "delay")
.parse::()
.unwrap(),
);
+ //quality_spin.set_value(
+ //config_management::get("default", "quality")
+ //.parse::()
+ //.unwrap(),
+ //);
+
+ let _format_chooser_combobox = format_chooser_combobox.clone();
+ let _quality_spin = quality_spin.clone();
+ format_chooser_combobox.connect_changed(move |_| {
+ if _format_chooser_combobox.active_text().is_some() {
+ config_management::set(
+ "default",
+ "format",
+ &_format_chooser_combobox.active().unwrap().to_string(),
+ );
+ let quality_spin = _quality_spin.clone();
+ _quality_spin.connect_value_changed(move |_| {
+ config_management::set(
+ "default",
+ "quality",
+ quality_spin.to_string().as_str(),
+ );
+ });
+ }
+ });
let _frames_spin = frames_spin.to_owned();
frames_spin.connect_value_changed(move |_| {
@@ -436,7 +443,17 @@ pub fn build_ui(application: &Application) {
});
let _delay_spin = delay_spin.to_owned();
delay_spin.connect_value_changed(move |_| {
- config_management::set("default", "delay", _delay_spin.value().to_string().as_str());
+ config_management::set("default",
+ "delay",
+ _delay_spin.value().to_string().as_str());
+ });
+ let _quality_spin = delay_spin.to_owned();
+ quality_spin.connect_value_changed(move |_| {
+ config_management::set(
+ "default",
+ "quality",
+ _quality_spin.value().to_string().as_str(),
+ );
});
// Labels
@@ -446,6 +463,8 @@ pub fn build_ui(application: &Application) {
.value().unwrap(), None, &mut vec![]).to_string());
delay_label.set_label(&bundle.format_pattern(bundle.get_message("delay").unwrap()
.value().unwrap(), None, &mut vec![]).to_string());
+ quality_label.set_label(&bundle.format_pattern(bundle.get_message("quality").unwrap()
+ .value().unwrap(), None, &mut vec![]).to_string());
audio_source_label.set_label(&bundle.format_pattern(bundle.get_message("audio-source").unwrap()
.value().unwrap(), None, &mut vec![]).to_string());
@@ -583,6 +602,7 @@ pub fn build_ui(application: &Application) {
main_context,
temp_video_filename: String::new(),
bundle: bundle_msg,
+ record_quality: quality_spin,
}));
// Record Button