mirror of
https://github.com/xlmnxp/blue-recorder.git
synced 2024-11-23 17:13:11 +03:00
split audio from video recording in Xorg then merge it with video
This commit is contained in:
parent
b299dd6042
commit
f39f2685a1
@ -1,7 +1,10 @@
|
||||
extern crate subprocess;
|
||||
use chrono::prelude::*;
|
||||
use gtk::prelude::*;
|
||||
use gtk::{CheckButton, ComboBoxText, Entry, FileChooser, ProgressBar, SpinButton, Window, WindowType, WindowPosition};
|
||||
use gtk::{
|
||||
CheckButton, ComboBoxText, Entry, FileChooser, ProgressBar, SpinButton, Window, WindowPosition,
|
||||
WindowType,
|
||||
};
|
||||
use std::collections::HashMap;
|
||||
use std::path::PathBuf;
|
||||
use std::process::Command;
|
||||
@ -96,15 +99,22 @@ pub struct Ffmpeg {
|
||||
pub record_frames: SpinButton,
|
||||
pub record_delay: SpinButton,
|
||||
pub command: Entry,
|
||||
pub process_id: Option<u32>,
|
||||
pub video_process_id: Option<u32>,
|
||||
pub audio_process_id: Option<u32>,
|
||||
pub saved_filename: Option<String>,
|
||||
pub unbound: Option<Sender<bool>>,
|
||||
pub progress_widget: ProgressWidget,
|
||||
}
|
||||
|
||||
impl Ffmpeg {
|
||||
pub fn start_record(&mut self, x: u16, y: u16, width: u16, height: u16) -> u32 {
|
||||
if self.process_id.is_some() {
|
||||
pub fn start_record(
|
||||
&mut self,
|
||||
x: u16,
|
||||
y: u16,
|
||||
width: u16,
|
||||
height: u16,
|
||||
) -> (Option<u32>, Option<u32>) {
|
||||
if self.video_process_id.is_some() || self.audio_process_id.is_some() {
|
||||
self.stop_record();
|
||||
}
|
||||
|
||||
@ -127,6 +137,22 @@ impl Ffmpeg {
|
||||
.to_string(),
|
||||
);
|
||||
|
||||
if self.record_audio.get_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.get_active_id().unwrap().to_string());
|
||||
ffmpeg_command.arg("-f");
|
||||
ffmpeg_command.arg("ogg");
|
||||
ffmpeg_command.arg(format!(
|
||||
"{}.temp.audio",
|
||||
self.saved_filename.as_ref().unwrap().to_string()
|
||||
));
|
||||
ffmpeg_command.arg("-y");
|
||||
self.audio_process_id = Some(ffmpeg_command.spawn().unwrap().id());
|
||||
}
|
||||
|
||||
if is_wayland() {
|
||||
if self.record_video.get_active() {
|
||||
if self.unbound.is_some() {
|
||||
@ -145,118 +171,106 @@ impl Ffmpeg {
|
||||
);
|
||||
}
|
||||
|
||||
if self.record_audio.get_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.get_active_id().unwrap().to_string());
|
||||
ffmpeg_command.arg("-f");
|
||||
ffmpeg_command.arg("ogg");
|
||||
ffmpeg_command.arg(format!(
|
||||
"{}.temp.audio",
|
||||
self.saved_filename.as_ref().unwrap().to_string()
|
||||
));
|
||||
ffmpeg_command.arg("-y");
|
||||
self.process_id = Some(ffmpeg_command.spawn().unwrap().id());
|
||||
}
|
||||
|
||||
return self.process_id.unwrap();
|
||||
return (None, self.audio_process_id);
|
||||
}
|
||||
|
||||
let mut ffmpeg_command: Command = Command::new("ffmpeg");
|
||||
|
||||
// if recorder video switch is enabled, record video with specified width and hight
|
||||
if self.record_video.get_active() {
|
||||
let mut ffmpeg_command: Command = Command::new("ffmpeg");
|
||||
|
||||
// record video with specified width and hight
|
||||
ffmpeg_command.arg("-video_size");
|
||||
ffmpeg_command.arg(format!("{}x{}", width, height));
|
||||
}
|
||||
|
||||
// if show mouse switch is enabled, draw the mouse to video
|
||||
ffmpeg_command.arg("-draw_mouse");
|
||||
if self.record_mouse.get_active() {
|
||||
ffmpeg_command.arg("1");
|
||||
} else {
|
||||
ffmpeg_command.arg("0");
|
||||
}
|
||||
|
||||
// if follow mouse switch is enabled, follow the mouse
|
||||
if self.follow_mouse.get_active() {
|
||||
ffmpeg_command.arg("-follow_mouse");
|
||||
ffmpeg_command.arg("centered");
|
||||
}
|
||||
|
||||
ffmpeg_command.arg("-framerate");
|
||||
ffmpeg_command.arg(format!("{}", self.record_frames.get_value()));
|
||||
ffmpeg_command.arg("-f");
|
||||
ffmpeg_command.arg("x11grab");
|
||||
ffmpeg_command.arg("-i");
|
||||
ffmpeg_command.arg(format!(
|
||||
"{}+{},{}",
|
||||
std::env::var("DISPLAY")
|
||||
.unwrap_or(":1".to_string())
|
||||
.as_str(),
|
||||
x,
|
||||
y
|
||||
));
|
||||
|
||||
// if follow audio switch is enabled, record the audio
|
||||
if self.record_audio.get_active() {
|
||||
// if show mouse switch is enabled, draw the mouse to video
|
||||
ffmpeg_command.arg("-draw_mouse");
|
||||
if self.record_mouse.get_active() {
|
||||
ffmpeg_command.arg("1");
|
||||
} else {
|
||||
ffmpeg_command.arg("0");
|
||||
}
|
||||
// if follow mouse switch is enabled, follow the mouse
|
||||
if self.follow_mouse.get_active() {
|
||||
ffmpeg_command.arg("-follow_mouse");
|
||||
ffmpeg_command.arg("centered");
|
||||
}
|
||||
ffmpeg_command.arg("-framerate");
|
||||
ffmpeg_command.arg(format!("{}", self.record_frames.get_value()));
|
||||
ffmpeg_command.arg("-f");
|
||||
ffmpeg_command.arg("pulse");
|
||||
ffmpeg_command.arg("x11grab");
|
||||
ffmpeg_command.arg("-i");
|
||||
ffmpeg_command.arg(self.audio_id.get_active_id().unwrap().to_string());
|
||||
ffmpeg_command.arg("-strict");
|
||||
ffmpeg_command.arg("-2");
|
||||
ffmpeg_command.arg(format!(
|
||||
"{}+{},{}",
|
||||
std::env::var("DISPLAY")
|
||||
.unwrap_or(":1".to_string())
|
||||
.as_str(),
|
||||
x,
|
||||
y
|
||||
));
|
||||
ffmpeg_command.arg("-q");
|
||||
ffmpeg_command.arg("1");
|
||||
ffmpeg_command.arg(self.saved_filename.as_ref().unwrap().to_string());
|
||||
ffmpeg_command.arg("-y");
|
||||
// sleep for delay
|
||||
sleep(Duration::from_secs(self.record_delay.get_value() as u64));
|
||||
// start recording and return the process id
|
||||
self.video_process_id = Some(ffmpeg_command.spawn().unwrap().id());
|
||||
return (self.video_process_id, self.audio_process_id);
|
||||
}
|
||||
|
||||
ffmpeg_command.arg("-q");
|
||||
ffmpeg_command.arg("1");
|
||||
|
||||
ffmpeg_command.arg(self.saved_filename.as_ref().unwrap());
|
||||
ffmpeg_command.arg("-y");
|
||||
|
||||
// sleep for delay
|
||||
sleep(Duration::from_secs(self.record_delay.get_value() as u64));
|
||||
|
||||
// start recording and return the process id
|
||||
self.process_id = Some(ffmpeg_command.spawn().unwrap().id());
|
||||
self.process_id.unwrap()
|
||||
(None, None)
|
||||
}
|
||||
|
||||
pub fn stop_record(&self) {
|
||||
&self.progress_widget.show();
|
||||
// kill the process to stop recording
|
||||
if self.process_id.is_some() {
|
||||
if self.video_process_id.is_some() {
|
||||
&self
|
||||
.progress_widget
|
||||
.set_progress("Stop Recording".to_string(), 1, 5);
|
||||
.set_progress("Stop Recording Video".to_string(), 1, 6);
|
||||
Command::new("kill")
|
||||
.arg(format!("{}", self.process_id.unwrap()))
|
||||
.arg(format!("{}", self.video_process_id.unwrap()))
|
||||
.output()
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
if is_wayland() {
|
||||
if self.audio_process_id.is_some() {
|
||||
&self
|
||||
.progress_widget
|
||||
.set_progress("Stop Recording Audio".to_string(), 2, 6);
|
||||
Command::new("kill")
|
||||
.arg(format!("{}", self.audio_process_id.unwrap()))
|
||||
.output()
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
let is_video_record = std::path::Path::new(
|
||||
format!(
|
||||
"{}{}",
|
||||
self.saved_filename.as_ref().unwrap_or(&String::from("")),
|
||||
if is_wayland() { ".temp" } else { "" }
|
||||
)
|
||||
.as_str(),
|
||||
)
|
||||
.exists();
|
||||
let is_audio_record = std::path::Path::new(
|
||||
format!(
|
||||
"{}.temp.audio",
|
||||
self.saved_filename.as_ref().unwrap_or(&String::from(""))
|
||||
)
|
||||
.as_str(),
|
||||
)
|
||||
.exists();
|
||||
|
||||
if is_video_record && is_wayland() {
|
||||
// create new dbus session
|
||||
let connection = zbus::Connection::new_session().unwrap();
|
||||
// bind the connection to gnome screencast proxy
|
||||
let gnome_screencast_proxy = GnomeScreencastProxy::new(&connection).unwrap();
|
||||
gnome_screencast_proxy.stop_screencast().unwrap();
|
||||
let is_audio_record = std::path::Path::new(
|
||||
format!("{}.temp.audio", self.saved_filename.as_ref().unwrap_or(&String::from(""))).as_str()
|
||||
)
|
||||
.exists();
|
||||
let is_video_record = std::path::Path::new(
|
||||
format!("{}.temp", self.saved_filename.as_ref().unwrap_or(&String::from(""))).as_str()
|
||||
)
|
||||
.exists();
|
||||
|
||||
if self.unbound.is_some() {
|
||||
&self.progress_widget.set_progress(
|
||||
"Stop Wayland Video Recording".to_string(),
|
||||
2,
|
||||
5,
|
||||
3,
|
||||
6,
|
||||
);
|
||||
self.unbound
|
||||
.as_ref()
|
||||
@ -288,86 +302,106 @@ impl Ffmpeg {
|
||||
ffmpeg_convert_command.output().unwrap();
|
||||
std::fs::remove_file(format!("{}.temp", self.saved_filename.as_ref().unwrap()))
|
||||
.unwrap();
|
||||
|
||||
if is_audio_record {
|
||||
&self.progress_widget.set_progress(
|
||||
"Stop Wayland Audio Recording".to_string(),
|
||||
3,
|
||||
5,
|
||||
);
|
||||
|
||||
// merge audio with video
|
||||
let mut ffmpeg_audio_merge_command = Command::new("ffmpeg");
|
||||
ffmpeg_audio_merge_command.arg("-i");
|
||||
ffmpeg_audio_merge_command.arg(format!(
|
||||
"{}.temp.without.audio.{}",
|
||||
self.saved_filename.as_ref().unwrap(),
|
||||
self.filename.2.get_active_id().unwrap().to_string()
|
||||
));
|
||||
ffmpeg_audio_merge_command.arg("-i");
|
||||
ffmpeg_audio_merge_command.arg(format!(
|
||||
"{}.temp.audio",
|
||||
self.saved_filename.as_ref().unwrap()
|
||||
));
|
||||
ffmpeg_audio_merge_command.arg("-c:v");
|
||||
ffmpeg_audio_merge_command.arg("copy");
|
||||
ffmpeg_audio_merge_command.arg("-c:a");
|
||||
ffmpeg_audio_merge_command.arg("aac");
|
||||
ffmpeg_audio_merge_command.arg(self.saved_filename.as_ref().unwrap());
|
||||
ffmpeg_audio_merge_command.arg("-y");
|
||||
ffmpeg_audio_merge_command.output().unwrap();
|
||||
std::fs::remove_file(format!(
|
||||
"{}.temp.audio",
|
||||
self.saved_filename.as_ref().unwrap()
|
||||
))
|
||||
.unwrap();
|
||||
std::fs::remove_file(format!(
|
||||
"{}.temp.without.audio.{}",
|
||||
self.saved_filename.as_ref().unwrap(),
|
||||
self.filename.2.get_active_id().unwrap().to_string()
|
||||
))
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
} else if is_audio_record {
|
||||
&self.progress_widget.set_progress(
|
||||
"Convert Audio to choosen format".to_string(),
|
||||
3,
|
||||
5,
|
||||
);
|
||||
println!("convert audio");
|
||||
Command::new("ffmpeg")
|
||||
.arg("-f")
|
||||
.arg("ogg")
|
||||
.arg("-i")
|
||||
.arg(format!(
|
||||
"{}.temp.audio",
|
||||
self.saved_filename.as_ref().unwrap()
|
||||
))
|
||||
.arg(format!("{}", self.saved_filename.as_ref().unwrap()))
|
||||
.output()
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
if is_video_record {
|
||||
let mut move_command = Command::new("mv");
|
||||
move_command.arg(format!(
|
||||
"{}{}",
|
||||
self.saved_filename.as_ref().unwrap(),
|
||||
if is_wayland() { ".temp" } else { "" }
|
||||
));
|
||||
move_command.arg(format!(
|
||||
"{}{}",
|
||||
self.saved_filename.as_ref().unwrap_or(&String::new()),
|
||||
if is_audio_record {
|
||||
format!(
|
||||
".temp.without.audio.{}",
|
||||
self.filename.2.get_active_id().unwrap().to_string()
|
||||
)
|
||||
} else {
|
||||
"".to_string()
|
||||
}
|
||||
));
|
||||
move_command.output().unwrap();
|
||||
|
||||
// if audio record, then merge video with audio
|
||||
if is_audio_record {
|
||||
&self
|
||||
.progress_widget
|
||||
.set_progress("Save Audio Recording".to_string(), 4, 6);
|
||||
|
||||
let mut ffmpeg_audio_merge_command = Command::new("ffmpeg");
|
||||
ffmpeg_audio_merge_command.arg("-i");
|
||||
ffmpeg_audio_merge_command.arg(format!(
|
||||
"{}.temp.without.audio.{}",
|
||||
self.saved_filename.as_ref().unwrap(),
|
||||
self.filename.2.get_active_id().unwrap().to_string()
|
||||
));
|
||||
ffmpeg_audio_merge_command.arg("-i");
|
||||
ffmpeg_audio_merge_command.arg(format!(
|
||||
"{}.temp.audio",
|
||||
self.saved_filename.as_ref().unwrap()
|
||||
));
|
||||
ffmpeg_audio_merge_command.arg("-c:v");
|
||||
ffmpeg_audio_merge_command.arg("copy");
|
||||
ffmpeg_audio_merge_command.arg("-c:a");
|
||||
ffmpeg_audio_merge_command.arg("aac");
|
||||
ffmpeg_audio_merge_command.arg(self.saved_filename.as_ref().unwrap());
|
||||
ffmpeg_audio_merge_command.arg("-y");
|
||||
sleep(Duration::from_secs(1));
|
||||
ffmpeg_audio_merge_command.output().unwrap();
|
||||
std::fs::remove_file(format!(
|
||||
"{}.temp.audio",
|
||||
self.saved_filename.as_ref().unwrap()
|
||||
))
|
||||
.unwrap();
|
||||
std::fs::remove_file(format!(
|
||||
"{}.temp.without.audio.{}",
|
||||
self.saved_filename.as_ref().unwrap(),
|
||||
self.filename.2.get_active_id().unwrap().to_string()
|
||||
))
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
// if only audio is recording then convert it to chosen fromat
|
||||
else if is_audio_record {
|
||||
&self
|
||||
.progress_widget
|
||||
.set_progress("Convert Audio to choosen format".to_string(), 4, 6);
|
||||
sleep(Duration::from_secs(1));
|
||||
Command::new("ffmpeg")
|
||||
.arg("-f")
|
||||
.arg("ogg")
|
||||
.arg("-i")
|
||||
.arg(format!(
|
||||
"{}.temp.audio",
|
||||
self.saved_filename.as_ref().unwrap()
|
||||
))
|
||||
.arg(format!("{}", self.saved_filename.as_ref().unwrap()))
|
||||
.output()
|
||||
.unwrap();
|
||||
std::fs::remove_file(format!(
|
||||
"{}.temp.audio",
|
||||
self.saved_filename.as_ref().unwrap()
|
||||
))
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
// execute command after finish recording
|
||||
if !(self.command.get_text().trim() == "") {
|
||||
&self.progress_widget.set_progress(
|
||||
"execute custom command after finish".to_string(),
|
||||
4,
|
||||
5,
|
||||
6,
|
||||
);
|
||||
Exec::shell(self.command.get_text().trim()).popen().unwrap();
|
||||
}
|
||||
|
||||
&self
|
||||
.progress_widget
|
||||
.set_progress("Finish".to_string(), 5, 5);
|
||||
.set_progress("Finish".to_string(), 6, 6);
|
||||
&self.progress_widget.hide();
|
||||
}
|
||||
|
||||
|
@ -290,7 +290,8 @@ fn main() {
|
||||
record_frames: frames_spin,
|
||||
record_delay: delay_spin,
|
||||
command: command_entry,
|
||||
process_id: None,
|
||||
video_process_id: None,
|
||||
audio_process_id: None,
|
||||
saved_filename: None,
|
||||
unbound: None,
|
||||
progress_widget: ProgressWidget::new(&main_window),
|
||||
|
Loading…
Reference in New Issue
Block a user