Until Actix Web 4, we need to use an older version of actix so that the runtime's match up to version 1.
96 lines
2.5 KiB
Rust
96 lines
2.5 KiB
Rust
use std::io::Result;
|
|
use std::path::Path;
|
|
use std::process::{Child, Command, ExitStatus, Stdio};
|
|
|
|
use actix::prelude::*;
|
|
use log::{debug, trace};
|
|
|
|
// ffmpeg -i test.mp4 -c:v h264 -flags +cgop -g 30 -hls_time 3 out.m3u8
|
|
// ffmpeg -i "filename.mp4" -preset veryfast -c:v libx264 -f hls -hls_list_size 100 -hls_time 2 -crf 24 -vf scale=1080:-2,setsar=1:1 attempt/vid_out.m3u8
|
|
|
|
pub struct StreamActor;
|
|
|
|
impl Actor for StreamActor {
|
|
type Context = Context<Self>;
|
|
}
|
|
|
|
pub struct ProcessMessage(pub String, pub Child);
|
|
|
|
impl Message for ProcessMessage {
|
|
type Result = Result<ExitStatus>;
|
|
}
|
|
|
|
impl Handler<ProcessMessage> for StreamActor {
|
|
type Result = Result<ExitStatus>;
|
|
|
|
fn handle(&mut self, msg: ProcessMessage, _ctx: &mut Self::Context) -> Self::Result {
|
|
trace!("Message received");
|
|
let mut process = msg.1;
|
|
let result = process.wait();
|
|
|
|
debug!(
|
|
"Finished waiting for: {:?}. Code: {:?}",
|
|
msg.0,
|
|
result
|
|
.as_ref()
|
|
.map_or(-1, |status| status.code().unwrap_or(-1))
|
|
);
|
|
result
|
|
}
|
|
}
|
|
|
|
pub async fn create_playlist(video_path: &str, playlist_file: &str) -> Result<Child> {
|
|
if Path::new(playlist_file).exists() {
|
|
debug!("Playlist already exists: {}", playlist_file);
|
|
return Err(std::io::Error::from(std::io::ErrorKind::AlreadyExists));
|
|
}
|
|
|
|
let result = Command::new("ffmpeg")
|
|
.arg("-i")
|
|
.arg(video_path)
|
|
.arg("-c:v")
|
|
.arg("h264")
|
|
.arg("-crf")
|
|
.arg("21")
|
|
.arg("-preset")
|
|
.arg("veryfast")
|
|
.arg("-hls_time")
|
|
.arg("3")
|
|
.arg("-hls_list_size")
|
|
.arg("100")
|
|
.arg("-vf")
|
|
.arg("scale=1080:-2,setsar=1:1")
|
|
.arg(playlist_file)
|
|
.stdout(Stdio::null())
|
|
.stderr(Stdio::null())
|
|
.spawn();
|
|
|
|
let start_time = std::time::Instant::now();
|
|
loop {
|
|
actix::clock::delay_for(std::time::Duration::from_secs(1)).await;
|
|
|
|
if Path::new(playlist_file).exists()
|
|
|| std::time::Instant::now() - start_time > std::time::Duration::from_secs(5)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
result
|
|
}
|
|
|
|
pub fn generate_video_thumbnail(path: &Path, destination: &Path) {
|
|
Command::new("ffmpeg")
|
|
.arg("-ss")
|
|
.arg("3")
|
|
.arg("-i")
|
|
.arg(path.to_str().unwrap())
|
|
.arg("-vframes")
|
|
.arg("1")
|
|
.arg("-f")
|
|
.arg("image2")
|
|
.arg(destination)
|
|
.output()
|
|
.expect("Failure to create video frame");
|
|
}
|