Serve video gifs when requested
This commit is contained in:
77
Cargo.lock
generated
77
Cargo.lock
generated
@@ -320,7 +320,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
|
checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"getrandom",
|
"getrandom 0.2.15",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"version_check",
|
"version_check",
|
||||||
"zerocopy",
|
"zerocopy",
|
||||||
@@ -599,7 +599,7 @@ checksum = "2b1866ecef4f2d06a0bb77880015fdf2b89e25a1c2e5addacb87e459c86dc67e"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"base64 0.22.1",
|
"base64 0.22.1",
|
||||||
"blowfish",
|
"blowfish",
|
||||||
"getrandom",
|
"getrandom 0.2.15",
|
||||||
"subtle",
|
"subtle",
|
||||||
"zeroize",
|
"zeroize",
|
||||||
]
|
]
|
||||||
@@ -1037,12 +1037,12 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "errno"
|
name = "errno"
|
||||||
version = "0.3.9"
|
version = "0.3.12"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba"
|
checksum = "cea14ef9355e3beab063703aa9dab15afd25f0667c341310c1e5274bb1d0da18"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"windows-sys 0.52.0",
|
"windows-sys 0.59.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1214,10 +1214,22 @@ dependencies = [
|
|||||||
"cfg-if",
|
"cfg-if",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
"libc",
|
"libc",
|
||||||
"wasi",
|
"wasi 0.11.0+wasi-snapshot-preview1",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "getrandom"
|
||||||
|
version = "0.3.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"r-efi",
|
||||||
|
"wasi 0.14.2+wasi-0.2.4",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gimli"
|
name = "gimli"
|
||||||
version = "0.31.1"
|
version = "0.31.1"
|
||||||
@@ -1632,6 +1644,7 @@ dependencies = [
|
|||||||
"rayon",
|
"rayon",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
"tempfile",
|
||||||
"tokio",
|
"tokio",
|
||||||
"walkdir",
|
"walkdir",
|
||||||
]
|
]
|
||||||
@@ -1802,9 +1815,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.164"
|
version = "0.2.173"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "433bfe06b8c75da9b2e3fbea6e5329ff87748f0b144ef75306e674c3f6f7c13f"
|
checksum = "d8cfeafaffdbc32176b64fb251369d52ea9f0a8fbc6f8759edffef7b525d64bb"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libfuzzer-sys"
|
name = "libfuzzer-sys"
|
||||||
@@ -1839,9 +1852,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "linux-raw-sys"
|
name = "linux-raw-sys"
|
||||||
version = "0.4.14"
|
version = "0.9.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89"
|
checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "litemap"
|
name = "litemap"
|
||||||
@@ -1974,7 +1987,7 @@ checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"log",
|
"log",
|
||||||
"wasi",
|
"wasi 0.11.0+wasi-snapshot-preview1",
|
||||||
"windows-sys 0.48.0",
|
"windows-sys 0.48.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -1987,7 +2000,7 @@ dependencies = [
|
|||||||
"hermit-abi",
|
"hermit-abi",
|
||||||
"libc",
|
"libc",
|
||||||
"log",
|
"log",
|
||||||
"wasi",
|
"wasi 0.11.0+wasi-snapshot-preview1",
|
||||||
"windows-sys 0.52.0",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -2432,6 +2445,12 @@ dependencies = [
|
|||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "r-efi"
|
||||||
|
version = "5.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rand"
|
name = "rand"
|
||||||
version = "0.8.5"
|
version = "0.8.5"
|
||||||
@@ -2459,7 +2478,7 @@ version = "0.6.4"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"getrandom",
|
"getrandom 0.2.15",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -2627,7 +2646,7 @@ checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"cc",
|
"cc",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"getrandom",
|
"getrandom 0.2.15",
|
||||||
"libc",
|
"libc",
|
||||||
"spin",
|
"spin",
|
||||||
"untrusted",
|
"untrusted",
|
||||||
@@ -2651,15 +2670,15 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustix"
|
name = "rustix"
|
||||||
version = "0.38.41"
|
version = "1.0.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d7f649912bc1495e167a6edee79151c84b1bad49748cb4f1f1167f459f6224f6"
|
checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.6.0",
|
"bitflags 2.6.0",
|
||||||
"errno",
|
"errno",
|
||||||
"libc",
|
"libc",
|
||||||
"linux-raw-sys",
|
"linux-raw-sys",
|
||||||
"windows-sys 0.52.0",
|
"windows-sys 0.59.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -2917,12 +2936,12 @@ checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tempfile"
|
name = "tempfile"
|
||||||
version = "3.14.0"
|
version = "3.20.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "28cce251fcbc87fac86a866eeb0d6c2d536fc16d06f184bb61aeae11aa4cee0c"
|
checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
|
||||||
"fastrand",
|
"fastrand",
|
||||||
|
"getrandom 0.3.3",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"rustix",
|
"rustix",
|
||||||
"windows-sys 0.59.0",
|
"windows-sys 0.59.0",
|
||||||
@@ -3324,6 +3343,15 @@ version = "0.11.0+wasi-snapshot-preview1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasi"
|
||||||
|
version = "0.14.2+wasi-0.2.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3"
|
||||||
|
dependencies = [
|
||||||
|
"wit-bindgen-rt",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen"
|
name = "wasm-bindgen"
|
||||||
version = "0.2.95"
|
version = "0.2.95"
|
||||||
@@ -3606,6 +3634,15 @@ dependencies = [
|
|||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wit-bindgen-rt"
|
||||||
|
version = "0.39.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.6.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "write16"
|
name = "write16"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
|
|||||||
@@ -42,3 +42,4 @@ opentelemetry_sdk = { version = "0.28.0", features = ["default", "rt-tokio-curre
|
|||||||
opentelemetry-otlp = { version = "0.28.0", features = ["default", "metrics", "tracing", "grpc-tonic"] }
|
opentelemetry-otlp = { version = "0.28.0", features = ["default", "metrics", "tracing", "grpc-tonic"] }
|
||||||
opentelemetry-stdout = "0.28.0"
|
opentelemetry-stdout = "0.28.0"
|
||||||
opentelemetry-appender-log = "0.28.0"
|
opentelemetry-appender-log = "0.28.0"
|
||||||
|
tempfile = "3.20.0"
|
||||||
@@ -134,10 +134,20 @@ pub enum PhotoSize {
|
|||||||
Thumb,
|
Thumb,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
pub struct ThumbnailRequest {
|
pub struct ThumbnailRequest {
|
||||||
pub path: String,
|
pub(crate) path: String,
|
||||||
pub size: Option<PhotoSize>,
|
pub(crate)size: Option<PhotoSize>,
|
||||||
|
#[serde(default)]
|
||||||
|
pub(crate)format: Option<ThumbnailFormat>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, PartialEq)]
|
||||||
|
pub enum ThumbnailFormat {
|
||||||
|
#[serde(rename = "gif")]
|
||||||
|
Gif,
|
||||||
|
#[serde(rename = "image")]
|
||||||
|
Image,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
|
|||||||
37
src/main.rs
37
src/main.rs
@@ -45,6 +45,7 @@ use crate::tags::*;
|
|||||||
use crate::video::actors::{
|
use crate::video::actors::{
|
||||||
create_playlist, generate_video_thumbnail, ProcessMessage, ScanDirectoryMessage,
|
create_playlist, generate_video_thumbnail, ProcessMessage, ScanDirectoryMessage,
|
||||||
};
|
};
|
||||||
|
use crate::video::generate_video_gifs;
|
||||||
use log::{debug, error, info, trace, warn};
|
use log::{debug, error, info, trace, warn};
|
||||||
use opentelemetry::trace::{Span, Status, TraceContextExt, Tracer};
|
use opentelemetry::trace::{Span, Status, TraceContextExt, Tracer};
|
||||||
use opentelemetry::{global, KeyValue};
|
use opentelemetry::{global, KeyValue};
|
||||||
@@ -98,23 +99,29 @@ async fn get_image(
|
|||||||
.expect("Error stripping base path prefix from thumbnail");
|
.expect("Error stripping base path prefix from thumbnail");
|
||||||
|
|
||||||
let thumbs = &app_state.thumbnail_path;
|
let thumbs = &app_state.thumbnail_path;
|
||||||
let thumb_path = Path::new(&thumbs).join(relative_path);
|
let mut thumb_path = Path::new(&thumbs).join(relative_path);
|
||||||
|
|
||||||
|
// If it's a video and GIF format is requested, try to serve GIF thumbnail
|
||||||
|
if req.format == Some(ThumbnailFormat::Gif) && is_video_file(&path) {
|
||||||
|
thumb_path = Path::new(&app_state.gif_path).join(relative_path);
|
||||||
|
thumb_path.set_extension("gif");
|
||||||
|
}
|
||||||
|
|
||||||
trace!("Thumbnail path: {:?}", thumb_path);
|
trace!("Thumbnail path: {:?}", thumb_path);
|
||||||
if let Ok(file) = NamedFile::open(&thumb_path) {
|
if let Ok(file) = NamedFile::open(&thumb_path) {
|
||||||
span.set_status(Status::Ok);
|
span.set_status(Status::Ok);
|
||||||
file.into_response(&request)
|
// The NamedFile will automatically set the correct content-type
|
||||||
} else {
|
return file.into_response(&request);
|
||||||
span.set_status(Status::error("Not found"));
|
|
||||||
HttpResponse::NotFound().finish()
|
|
||||||
}
|
}
|
||||||
} else if let Ok(file) = NamedFile::open(path) {
|
}
|
||||||
|
|
||||||
|
if let Ok(file) = NamedFile::open(&path) {
|
||||||
span.set_status(Status::Ok);
|
span.set_status(Status::Ok);
|
||||||
file.into_response(&request)
|
return file.into_response(&request);
|
||||||
} else {
|
}
|
||||||
|
|
||||||
span.set_status(Status::error("Not found"));
|
span.set_status(Status::error("Not found"));
|
||||||
HttpResponse::NotFound().finish()
|
HttpResponse::NotFound().finish()
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
span.set_status(Status::error("Bad photos request"));
|
span.set_status(Status::error("Bad photos request"));
|
||||||
error!("Bad photos request: {}", req.path);
|
error!("Bad photos request: {}", req.path);
|
||||||
@@ -122,6 +129,17 @@ async fn get_image(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_video_file(path: &Path) -> bool {
|
||||||
|
if let Some(extension) = path.extension() {
|
||||||
|
matches!(
|
||||||
|
extension.to_str().unwrap_or("").to_lowercase().as_str(),
|
||||||
|
"mp4" | "mov" | "avi" | "mkv"
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[get("/image/metadata")]
|
#[get("/image/metadata")]
|
||||||
async fn get_file_metadata(
|
async fn get_file_metadata(
|
||||||
_: Claims,
|
_: Claims,
|
||||||
@@ -591,6 +609,7 @@ fn main() -> std::io::Result<()> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
create_thumbnails();
|
create_thumbnails();
|
||||||
|
generate_video_gifs().await;
|
||||||
|
|
||||||
let app_data = Data::new(AppState::default());
|
let app_data = Data::new(AppState::default());
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ pub struct AppState {
|
|||||||
pub base_path: String,
|
pub base_path: String,
|
||||||
pub thumbnail_path: String,
|
pub thumbnail_path: String,
|
||||||
pub video_path: String,
|
pub video_path: String,
|
||||||
|
pub gif_path: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AppState {
|
impl AppState {
|
||||||
@@ -16,6 +17,7 @@ impl AppState {
|
|||||||
base_path: String,
|
base_path: String,
|
||||||
thumbnail_path: String,
|
thumbnail_path: String,
|
||||||
video_path: String,
|
video_path: String,
|
||||||
|
gif_path: String,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let playlist_generator = PlaylistGenerator::new();
|
let playlist_generator = PlaylistGenerator::new();
|
||||||
let video_playlist_manager =
|
let video_playlist_manager =
|
||||||
@@ -27,6 +29,7 @@ impl AppState {
|
|||||||
base_path,
|
base_path,
|
||||||
thumbnail_path,
|
thumbnail_path,
|
||||||
video_path,
|
video_path,
|
||||||
|
gif_path,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -38,6 +41,7 @@ impl Default for AppState {
|
|||||||
env::var("BASE_PATH").expect("BASE_PATH was not set in the env"),
|
env::var("BASE_PATH").expect("BASE_PATH was not set in the env"),
|
||||||
env::var("THUMBNAILS").expect("THUMBNAILS was not set in the env"),
|
env::var("THUMBNAILS").expect("THUMBNAILS was not set in the env"),
|
||||||
env::var("VIDEO_PATH").expect("VIDEO_PATH was not set in the env"),
|
env::var("VIDEO_PATH").expect("VIDEO_PATH was not set in the env"),
|
||||||
|
env::var("GIFS_DIRECTORY").expect("GIFS_DIRECTORY was not set in the env"),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -156,7 +156,7 @@ impl Ffmpeg {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn create_gif_from_frames(&self, frame_base_dir: &str, output_file: &str) -> Result<i32> {
|
async fn create_gif_from_frames(&self, frame_base_dir: &str, output_file: &str) -> Result<i32> {
|
||||||
Command::new("ffmpeg")
|
let output = Command::new("ffmpeg")
|
||||||
.arg("-y")
|
.arg("-y")
|
||||||
.args(["-framerate", "4"])
|
.args(["-framerate", "4"])
|
||||||
.args(["-i", &format!("{}/frame_%03d.jpg", frame_base_dir)])
|
.args(["-i", &format!("{}/frame_%03d.jpg", frame_base_dir)])
|
||||||
@@ -169,10 +169,20 @@ impl Ffmpeg {
|
|||||||
.args(["-loop", "0"]) // loop forever
|
.args(["-loop", "0"]) // loop forever
|
||||||
.args(["-final_delay", "75"])
|
.args(["-final_delay", "75"])
|
||||||
.arg(output_file)
|
.arg(output_file)
|
||||||
.stderr(Stdio::null())
|
.stderr(Stdio::piped()) // Change this to capture stderr
|
||||||
.status()
|
.stdout(Stdio::piped()) // Optionally capture stdout too
|
||||||
.map_ok(|out| out.code().unwrap_or(-1))
|
.output()
|
||||||
.inspect_ok(|output| debug!("ffmpeg gif create exit code: {:?}", output))
|
.await?;
|
||||||
.await
|
|
||||||
|
if !output.status.success() {
|
||||||
|
let stderr = String::from_utf8_lossy(&output.stderr);
|
||||||
|
error!("FFmpeg error: {}", stderr);
|
||||||
|
let stdout = String::from_utf8_lossy(&output.stdout);
|
||||||
|
debug!("FFmpeg stdout: {}", stdout);
|
||||||
|
} else {
|
||||||
|
debug!("FFmpeg successful with exit code: {}", output.status);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(output.status.code().unwrap_or(-1))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,2 +1,67 @@
|
|||||||
|
use crate::otel::global_tracer;
|
||||||
|
use crate::video::ffmpeg::{Ffmpeg, GifType};
|
||||||
|
use crate::{is_video, update_media_counts};
|
||||||
|
use log::{info};
|
||||||
|
use opentelemetry::trace::{Tracer};
|
||||||
|
use std::path::{Path, PathBuf};
|
||||||
|
use std::{fs};
|
||||||
|
use walkdir::WalkDir;
|
||||||
|
|
||||||
pub mod actors;
|
pub mod actors;
|
||||||
pub mod ffmpeg;
|
pub mod ffmpeg;
|
||||||
|
|
||||||
|
pub async fn generate_video_gifs() {
|
||||||
|
tokio::spawn(async {
|
||||||
|
info!("Starting to make video gifs");
|
||||||
|
|
||||||
|
let start = std::time::Instant::now();
|
||||||
|
let tracer = global_tracer();
|
||||||
|
let span = tracer.start("creating video gifs");
|
||||||
|
|
||||||
|
let gif_base_path = &dotenv::var("GIFS_DIRECTORY").unwrap_or(String::from("gifs"));
|
||||||
|
let gif_directory: &Path = Path::new(gif_base_path);
|
||||||
|
fs::create_dir_all(gif_base_path).expect("There was an issue creating directory");
|
||||||
|
|
||||||
|
let files = PathBuf::from(dotenv::var("BASE_PATH").unwrap());
|
||||||
|
|
||||||
|
let ffmpeg = Ffmpeg;
|
||||||
|
for file in WalkDir::new(&files)
|
||||||
|
.into_iter()
|
||||||
|
.filter_map(|entry| entry.ok())
|
||||||
|
.filter(|entry| entry.file_type().is_file())
|
||||||
|
.filter(|entry| is_video(entry))
|
||||||
|
.filter(|entry| {
|
||||||
|
let path = entry.path();
|
||||||
|
let relative_path = &path.strip_prefix(&files).unwrap();
|
||||||
|
let thumb_path = Path::new(gif_directory).join(relative_path);
|
||||||
|
let gif_path = thumb_path.with_extension("gif");
|
||||||
|
!gif_path.exists()
|
||||||
|
})
|
||||||
|
{
|
||||||
|
let path = file.path();
|
||||||
|
let relative_path = &path.strip_prefix(&files).unwrap();
|
||||||
|
let gif_path = Path::new(gif_directory).join(relative_path);
|
||||||
|
let gif_path = gif_path.with_extension("gif");
|
||||||
|
if let Some(parent_dir) = gif_path.parent() {
|
||||||
|
fs::create_dir_all(parent_dir).expect(&format!(
|
||||||
|
"There was an issue creating gif directory {:?}",
|
||||||
|
gif_path
|
||||||
|
));
|
||||||
|
}
|
||||||
|
info!("Generating gif for {:?}", path);
|
||||||
|
|
||||||
|
ffmpeg
|
||||||
|
.generate_video_gif(
|
||||||
|
path.to_str().unwrap(),
|
||||||
|
gif_path.to_str().unwrap(),
|
||||||
|
GifType::Overview,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.expect("There was an issue generating the gif");
|
||||||
|
}
|
||||||
|
|
||||||
|
info!("Finished making video gifs in {:?}", start.elapsed());
|
||||||
|
|
||||||
|
update_media_counts(&files);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user