Improve gif handling.

- Allow a fast-path exif cleaning if we'd re-encode a gif to a gif
- Use single-frame palettes to better map transparency from frame to frame

Unrelated:
- decrease ffmpeg logging when creating thumbnails
This commit is contained in:
asonix 2023-06-19 14:25:22 -05:00
parent 0833271281
commit a3a986638d
2 changed files with 31 additions and 7 deletions

View File

@ -50,6 +50,13 @@ impl TranscodeOptions {
} }
} }
pub(crate) const fn needs_reencode(&self) -> bool {
!matches!(
(self.input_format, &self.output),
(VideoFormat::Gif, TranscodeOutputOptions::Gif)
)
}
const fn input_file_extension(&self) -> &'static str { const fn input_file_extension(&self) -> &'static str {
self.input_format.to_file_extension() self.input_format.to_file_extension()
} }
@ -92,10 +99,12 @@ impl TranscodeOptions {
match self.output { match self.output {
TranscodeOutputOptions::Gif => Process::run("ffmpeg", &[ TranscodeOutputOptions::Gif => Process::run("ffmpeg", &[
"-hide_banner", "-hide_banner",
"-v",
"warning",
"-i", "-i",
input_path, input_path,
"-filter_complex", "-filter_complex",
"[0:v] split [a][b]; [a] palettegen=reserve_transparent=on:transparency_color=ffffff [p]; [b][p] paletteuse", "[0:v] split [a][b]; [a] palettegen=stats_mode=single [p]; [b][p] paletteuse=new=1",
"-an", "-an",
"-f", "-f",
self.output_ffmpeg_format(), self.output_ffmpeg_format(),
@ -108,6 +117,8 @@ impl TranscodeOptions {
"ffmpeg", "ffmpeg",
&[ &[
"-hide_banner", "-hide_banner",
"-v",
"warning",
"-i", "-i",
input_path, input_path,
"-pix_fmt", "-pix_fmt",
@ -129,6 +140,8 @@ impl TranscodeOptions {
"ffmpeg", "ffmpeg",
&[ &[
"-hide_banner", "-hide_banner",
"-v",
"warning",
"-i", "-i",
input_path, input_path,
"-pix_fmt", "-pix_fmt",
@ -576,6 +589,8 @@ pub(crate) async fn thumbnail<S: Store>(
"ffmpeg", "ffmpeg",
&[ &[
"-hide_banner", "-hide_banner",
"-v",
"warning",
"-i", "-i",
input_file_str, input_file_str,
"-frames:v", "-frames:v",

View File

@ -59,12 +59,21 @@ pub(crate) async fn validate_bytes(
} }
let transcode_options = TranscodeOptions::new(media, &details, video_format); let transcode_options = TranscodeOptions::new(media, &details, video_format);
Ok(( if transcode_options.needs_reencode() {
transcode_options.output_type(), Ok((
Either::right(Either::left(Either::left( transcode_options.output_type(),
crate::ffmpeg::transcode_bytes(bytes, transcode_options).await?, Either::right(Either::left(Either::left(
))), crate::ffmpeg::transcode_bytes(bytes, transcode_options).await?,
)) ))),
))
} else {
Ok((
transcode_options.output_type(),
Either::right(Either::right(crate::exiftool::clear_metadata_bytes_read(
bytes,
)?)),
))
}
} }
(FileFormat::Image(image_format), Some(format)) if image_format != format => Ok(( (FileFormat::Image(image_format), Some(format)) if image_format != format => Ok((
ValidInputType::from_format(format), ValidInputType::from_format(format),