fix: probe files for no-compress
This commit is contained in:
parent
6ed693f13a
commit
7767d21ccf
19
migrations/20240529112336_upload_labels.sql
Normal file
19
migrations/20240529112336_upload_labels.sql
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
-- Add migration script here
|
||||||
|
alter table uploads
|
||||||
|
add column blur_hash varchar(512),
|
||||||
|
add column width integer unsigned,
|
||||||
|
add column height integer unsigned;
|
||||||
|
|
||||||
|
create table upload_labels
|
||||||
|
(
|
||||||
|
file binary(32) not null,
|
||||||
|
label varchar(255) not null,
|
||||||
|
created timestamp default current_timestamp,
|
||||||
|
model varchar(255) not null,
|
||||||
|
|
||||||
|
constraint fk_upload_labels_file_id
|
||||||
|
foreign key (file) references uploads (id)
|
||||||
|
on delete cascade
|
||||||
|
on update restrict
|
||||||
|
);
|
||||||
|
create unique index ix_upload_labels_file_label_model on upload_labels (file, label, model);
|
@ -13,7 +13,7 @@ use tokio::fs::File;
|
|||||||
use tokio::io::{AsyncRead, AsyncReadExt, AsyncSeekExt};
|
use tokio::io::{AsyncRead, AsyncReadExt, AsyncSeekExt};
|
||||||
|
|
||||||
use crate::db::{FileLabel, FileUpload};
|
use crate::db::{FileLabel, FileUpload};
|
||||||
use crate::processing::{compress_file, FileProcessorResult};
|
use crate::processing::{compress_file, FileProcessorResult, probe_file, ProbeResult, ProbeStream};
|
||||||
use crate::processing::labeling::label_frame;
|
use crate::processing::labeling::label_frame;
|
||||||
use crate::settings::Settings;
|
use crate::settings::Settings;
|
||||||
|
|
||||||
@ -148,7 +148,34 @@ impl FileStore {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
} else if let FileProcessorResult::Probe(p) = probe_file(tmp_path.clone())? {
|
||||||
|
let video_stream_size = p.streams.iter().find_map(|s| match s {
|
||||||
|
ProbeStream::Video { width, height, .. } => Some((width, height)),
|
||||||
|
_ => None
|
||||||
|
});
|
||||||
|
let n = file.metadata().await?.len();
|
||||||
|
let hash = FileStore::hash_file(&mut file).await?;
|
||||||
|
return Ok(FileSystemResult {
|
||||||
|
path: tmp_path,
|
||||||
|
upload: FileUpload {
|
||||||
|
id: hash,
|
||||||
|
name: "".to_string(),
|
||||||
|
size: n,
|
||||||
|
created: Utc::now(),
|
||||||
|
mime_type: mime_type.to_string(),
|
||||||
|
width: match video_stream_size {
|
||||||
|
Some((w, _h)) => Some(*w),
|
||||||
|
_ => None
|
||||||
|
},
|
||||||
|
height: match video_stream_size {
|
||||||
|
Some((_w, h)) => Some(*h),
|
||||||
|
_ => None
|
||||||
|
},
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let n = file.metadata().await?.len();
|
let n = file.metadata().await?.len();
|
||||||
let hash = FileStore::hash_file(&mut file).await?;
|
let hash = FileStore::hash_file(&mut file).await?;
|
||||||
Ok(FileSystemResult {
|
Ok(FileSystemResult {
|
||||||
@ -158,6 +185,7 @@ impl FileStore {
|
|||||||
name: "".to_string(),
|
name: "".to_string(),
|
||||||
size: n,
|
size: n,
|
||||||
created: Utc::now(),
|
created: Utc::now(),
|
||||||
|
mime_type: mime_type.to_string(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
@ -4,6 +4,7 @@ use std::ptr;
|
|||||||
|
|
||||||
use anyhow::Error;
|
use anyhow::Error;
|
||||||
use ffmpeg_sys_the_third::{av_frame_alloc, AVFrame, AVPixelFormat, sws_freeContext, sws_getContext, sws_scale_frame};
|
use ffmpeg_sys_the_third::{av_frame_alloc, AVFrame, AVPixelFormat, sws_freeContext, sws_getContext, sws_scale_frame};
|
||||||
|
use crate::processing::probe::FFProbe;
|
||||||
|
|
||||||
use crate::processing::webp::WebpProcessor;
|
use crate::processing::webp::WebpProcessor;
|
||||||
|
|
||||||
@ -56,6 +57,11 @@ pub fn compress_file(in_file: PathBuf, mime_type: &str) -> Result<FileProcessorR
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn probe_file(in_file: PathBuf) -> Result<FileProcessorResult, Error> {
|
||||||
|
let proc = FFProbe::new();
|
||||||
|
proc.process_file(in_file, "")
|
||||||
|
}
|
||||||
|
|
||||||
unsafe fn resize_image(frame: *const AVFrame, width: usize, height: usize, pix_fmt: AVPixelFormat) -> Result<*mut AVFrame, Error> {
|
unsafe fn resize_image(frame: *const AVFrame, width: usize, height: usize, pix_fmt: AVPixelFormat) -> Result<*mut AVFrame, Error> {
|
||||||
let sws_ctx = sws_getContext((*frame).width,
|
let sws_ctx = sws_getContext((*frame).width,
|
||||||
(*frame).height,
|
(*frame).height,
|
||||||
@ -76,4 +82,4 @@ unsafe fn resize_image(frame: *const AVFrame, width: usize, height: usize, pix_f
|
|||||||
|
|
||||||
sws_freeContext(sws_ctx);
|
sws_freeContext(sws_ctx);
|
||||||
Ok(dst_frame)
|
Ok(dst_frame)
|
||||||
}
|
}
|
||||||
|
64
src/processing/probe.rs
Normal file
64
src/processing/probe.rs
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
use std::ffi::CStr;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use std::ptr;
|
||||||
|
|
||||||
|
use anyhow::Error;
|
||||||
|
use ffmpeg_sys_the_third::{avcodec_get_name, avformat_close_input, avformat_find_stream_info, avformat_free_context, avformat_open_input, AVFormatContext};
|
||||||
|
use ffmpeg_sys_the_third::AVMediaType::{AVMEDIA_TYPE_AUDIO, AVMEDIA_TYPE_VIDEO};
|
||||||
|
|
||||||
|
use crate::processing::{FileProcessorResult, ProbeResult, ProbeStream};
|
||||||
|
|
||||||
|
/// Image converter to WEBP
|
||||||
|
pub struct FFProbe {}
|
||||||
|
|
||||||
|
impl FFProbe {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn process_file(mut self, in_file: PathBuf, mime_type: &str) -> Result<FileProcessorResult, Error> {
|
||||||
|
unsafe {
|
||||||
|
let mut dec_fmt: *mut AVFormatContext = ptr::null_mut();
|
||||||
|
let ret = avformat_open_input(&mut dec_fmt,
|
||||||
|
format!("{}\0", in_file.into_os_string().into_string().unwrap()).as_ptr() as *const libc::c_char,
|
||||||
|
ptr::null_mut(),
|
||||||
|
ptr::null_mut());
|
||||||
|
if ret < 0 {
|
||||||
|
return Err(Error::msg("Failed to create input context"));
|
||||||
|
}
|
||||||
|
|
||||||
|
let ret = avformat_find_stream_info(dec_fmt, ptr::null_mut());
|
||||||
|
if ret < 0 {
|
||||||
|
return Err(Error::msg("Failed to probe input"));
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut stream_info = vec![];
|
||||||
|
let mut ptr_x = 0;
|
||||||
|
while ptr_x < (*dec_fmt).nb_streams {
|
||||||
|
let ptr = *(*dec_fmt).streams.add(ptr_x as usize);
|
||||||
|
let codec_par = (*ptr).codecpar;
|
||||||
|
let codec = CStr::from_ptr(avcodec_get_name((*codec_par).codec_id)).to_str()?.to_string();
|
||||||
|
if (*codec_par).codec_type == AVMEDIA_TYPE_VIDEO {
|
||||||
|
stream_info.push(ProbeStream::Video {
|
||||||
|
width: (*codec_par).width as u32,
|
||||||
|
height: (*codec_par).height as u32,
|
||||||
|
codec,
|
||||||
|
});
|
||||||
|
} else if (*codec_par).codec_type == AVMEDIA_TYPE_AUDIO {
|
||||||
|
stream_info.push(ProbeStream::Audio {
|
||||||
|
sample_rate: (*codec_par).sample_rate as u32,
|
||||||
|
codec,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
ptr_x += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
avformat_close_input(&mut dec_fmt);
|
||||||
|
avformat_free_context(dec_fmt);
|
||||||
|
|
||||||
|
Ok(FileProcessorResult::Probe(ProbeResult {
|
||||||
|
streams: stream_info
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user