remove debug logs, fix up readme
This commit is contained in:
parent
5f8901d53e
commit
4e09c735dd
3 changed files with 29 additions and 33 deletions
|
@ -6,10 +6,15 @@ For all those who want to post memes that are just too big and surpass the 25mb
|
||||||
- video codec: vp9 + opus .webm
|
- video codec: vp9 + opus .webm
|
||||||
- image codec: vp8 .webp (for gifs too)
|
- image codec: vp8 .webp (for gifs too)
|
||||||
|
|
||||||
## How to install(Windows, Linux, MacOS):
|
##How to install Binary(Windows, Linux):
|
||||||
|
1. Download binary from [Releases](https://github.com/djkato/n-mb/releases), put into $PATH
|
||||||
|
2. get ffmpeg for your platform [here](https://ffmpeg.org/download.html), put into $PATH
|
||||||
|
3. execute anywhere using the `nmb --size/-s <SIZE IN MB> --codec/-c <WEBM/HEVC> --files/-f=<FILE 1>,<FILE 2> . . .` command!
|
||||||
|
|
||||||
|
## How to install From Source(Windows, Linux, MacOS):
|
||||||
1. get rustup (cargo, rustc etc) from [here](https://www.rust-lang.org/tools/install)
|
1. get rustup (cargo, rustc etc) from [here](https://www.rust-lang.org/tools/install)
|
||||||
2. get ffmpeg for your platform [here](https://ffmpeg.org/download.html), put into $PATH
|
2. get ffmpeg for your platform [here](https://ffmpeg.org/download.html), put into $PATH
|
||||||
3. run `cargo install n-mb` in your favourite terminal
|
3. run `cargo install n-mb` in your favourite terminal
|
||||||
4. execute anywhere using the `nmb --size/-s <SIZE IN MB> --files/-f=<FILE 1>,<FILE 2> . . .` command!
|
4. execute anywhere using the `nmb --size/-s <SIZE IN MB> --codec/-c <WEBM/HEVC> --files/-f=<FILE 1>,<FILE 2> . . .` command!
|
||||||
|
|
||||||
<sub>Thanks for an amazing read on how to optimize vp9 for file sizes deterenkelt, I recommend this read: https://codeberg.org/deterenkelt/Nadeshiko/wiki/Researches%E2%80%89%E2%80%93%E2%80%89VP9-and-overshooting</sub>
|
<sub>Thanks for an amazing read on how to optimize vp9 for file sizes deterenkelt, I recommend this read: https://codeberg.org/deterenkelt/Nadeshiko/wiki/Researches%E2%80%89%E2%80%93%E2%80%89VP9-and-overshooting</sub>
|
||||||
|
|
|
@ -8,7 +8,7 @@ use tokio::{
|
||||||
|
|
||||||
use crate::VideoCodec;
|
use crate::VideoCodec;
|
||||||
const MAX_OPUS_BITRATE: f32 = 256.; //kbits
|
const MAX_OPUS_BITRATE: f32 = 256.; //kbits
|
||||||
const MIN_OPUS_BITRATE: f32 = 56.; //kbits
|
const MIN_OPUS_BITRATE: f32 = 50.; //kbits
|
||||||
|
|
||||||
pub struct FFMPEGCommand {
|
pub struct FFMPEGCommand {
|
||||||
pub file_name: String,
|
pub file_name: String,
|
||||||
|
@ -60,7 +60,7 @@ impl FFMPEGCommand {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let bitrate = (size as f32 * 1000. / duration) * 0.9;
|
let bitrate = (size as f32 * 1000. / duration) * 0.85;
|
||||||
let bitrate = bitrate.clamp(MIN_OPUS_BITRATE, max_kbit_rate) as u16;
|
let bitrate = bitrate.clamp(MIN_OPUS_BITRATE, max_kbit_rate) as u16;
|
||||||
/*
|
/*
|
||||||
println!(
|
println!(
|
||||||
|
@ -136,7 +136,7 @@ impl FFMPEGCommand {
|
||||||
video_bitrate + audio_bitrate,
|
video_bitrate + audio_bitrate,
|
||||||
size
|
size
|
||||||
);*/
|
);*/
|
||||||
video_bitrate = video_bitrate + overflow;
|
video_bitrate += overflow;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut height = resolution.1;
|
let mut height = resolution.1;
|
||||||
|
@ -265,7 +265,6 @@ impl FFMPEGCommand {
|
||||||
.to_str()
|
.to_str()
|
||||||
.context("missing or bad path")?,
|
.context("missing or bad path")?,
|
||||||
]);
|
]);
|
||||||
dbg!(&command2);
|
|
||||||
Ok(FFMPEGCommand {
|
Ok(FFMPEGCommand {
|
||||||
file_name: path.file_name().unwrap().to_str().unwrap().to_owned(),
|
file_name: path.file_name().unwrap().to_str().unwrap().to_owned(),
|
||||||
resolution: None,
|
resolution: None,
|
||||||
|
@ -317,7 +316,7 @@ impl FFMPEGCommand {
|
||||||
progress_bar: None,
|
progress_bar: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
fn create_animated_image(path: &PathBuf) -> anyhow::Result<Self> {
|
fn create_animated_image(_path: &PathBuf) -> anyhow::Result<Self> {
|
||||||
bail!("")
|
bail!("")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -362,24 +361,24 @@ async fn parse_ffprobe(path: &PathBuf) -> anyhow::Result<MediaData> {
|
||||||
if text.contains("Stream") {
|
if text.contains("Stream") {
|
||||||
resolution = parse_resolution(text).ok();
|
resolution = parse_resolution(text).ok();
|
||||||
}
|
}
|
||||||
return Ok(MediaData {
|
Ok(MediaData {
|
||||||
duration,
|
duration,
|
||||||
resolution,
|
resolution,
|
||||||
old_kbit_rate,
|
old_kbit_rate,
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_duration(text: &str) -> anyhow::Result<f32> {
|
fn parse_duration(text: &str) -> anyhow::Result<f32> {
|
||||||
let text = text[text.find("Duration").unwrap()..].to_owned();
|
let text = text[text.find("Duration").unwrap()..].to_owned();
|
||||||
let dur_text = text[text
|
let dur_text = text[text
|
||||||
.find(":")
|
.find(':')
|
||||||
.context("something wrong with the ffprobe output")?
|
.context("something wrong with the ffprobe output")?
|
||||||
+ 2
|
+ 2
|
||||||
..text
|
..text
|
||||||
.find(",")
|
.find(',')
|
||||||
.context("something wrong with the ffprobe output")?]
|
.context("something wrong with the ffprobe output")?]
|
||||||
.to_owned();
|
.to_owned();
|
||||||
let durs_text: Vec<&str> = dur_text.split(":").collect();
|
let durs_text: Vec<&str> = dur_text.split(':').collect();
|
||||||
let mut durs_text_iter = durs_text.into_iter();
|
let mut durs_text_iter = durs_text.into_iter();
|
||||||
let h = durs_text_iter
|
let h = durs_text_iter
|
||||||
.next()
|
.next()
|
||||||
|
@ -398,7 +397,7 @@ fn parse_duration(text: &str) -> anyhow::Result<f32> {
|
||||||
|
|
||||||
fn parse_bitrate(text: &str) -> anyhow::Result<u16> {
|
fn parse_bitrate(text: &str) -> anyhow::Result<u16> {
|
||||||
let text = text[text.find("bitrate").unwrap()..].to_owned();
|
let text = text[text.find("bitrate").unwrap()..].to_owned();
|
||||||
let bitrate_text = text[9..text.find("/").unwrap() - 2].to_owned();
|
let bitrate_text = text[9..text.find('/').unwrap() - 2].to_owned();
|
||||||
|
|
||||||
Ok(bitrate_text.parse::<u16>()?)
|
Ok(bitrate_text.parse::<u16>()?)
|
||||||
}
|
}
|
||||||
|
@ -411,7 +410,7 @@ fn parse_resolution(text: &str) -> anyhow::Result<(u16, u16)> {
|
||||||
- 1;
|
- 1;
|
||||||
|
|
||||||
let rb_b4_sar_i = text[..sar_i]
|
let rb_b4_sar_i = text[..sar_i]
|
||||||
.rfind(",")
|
.rfind(',')
|
||||||
.context("something wrong with the ffprobe output")?
|
.context("something wrong with the ffprobe output")?
|
||||||
+ 1;
|
+ 1;
|
||||||
|
|
||||||
|
@ -419,17 +418,17 @@ fn parse_resolution(text: &str) -> anyhow::Result<(u16, u16)> {
|
||||||
let res_text = res_text.trim().to_owned();
|
let res_text = res_text.trim().to_owned();
|
||||||
|
|
||||||
let width = res_text[..res_text
|
let width = res_text[..res_text
|
||||||
.find("x")
|
.find('x')
|
||||||
.context("something wrong with ffprobe output")?]
|
.context("something wrong with ffprobe output")?]
|
||||||
.to_owned()
|
.to_owned()
|
||||||
.parse::<u16>()?;
|
.parse::<u16>()?;
|
||||||
|
|
||||||
let height = res_text[res_text
|
let height = res_text[res_text
|
||||||
.find("x")
|
.find('x')
|
||||||
.context("something wrong with ffprobe output")?
|
.context("something wrong with ffprobe output")?
|
||||||
+ 1..]
|
+ 1..]
|
||||||
.to_owned()
|
.to_owned()
|
||||||
.parse::<u16>()?;
|
.parse::<u16>()?;
|
||||||
|
|
||||||
return Ok((width, height));
|
Ok((width, height))
|
||||||
}
|
}
|
||||||
|
|
22
src/main.rs
22
src/main.rs
|
@ -1,7 +1,7 @@
|
||||||
#![feature(exit_status_error)]
|
#![feature(exit_status_error)]
|
||||||
|
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
use clap::{arg, command, value_parser, ValueEnum};
|
use clap::{arg, command, value_parser};
|
||||||
use encoder::{FFMPEGCommand, MediaType};
|
use encoder::{FFMPEGCommand, MediaType};
|
||||||
use std::{path::PathBuf, process::Stdio, sync::Arc};
|
use std::{path::PathBuf, process::Stdio, sync::Arc};
|
||||||
use tokio::{
|
use tokio::{
|
||||||
|
@ -91,31 +91,23 @@ async fn main() -> anyhow::Result<()> {
|
||||||
{
|
{
|
||||||
"webm" | "mp4" | "mov" | "avi" | "mpeg" | "mkv" => {
|
"webm" | "mp4" | "mov" | "avi" | "mpeg" | "mkv" => {
|
||||||
command =
|
command =
|
||||||
FFMPEGCommand::new(MediaType::Video, file, size.clone(), codec.clone())
|
FFMPEGCommand::new(MediaType::Video, file, size, codec.clone()).await?;
|
||||||
.await?;
|
|
||||||
}
|
}
|
||||||
"mp3" | "wav" | "ogg" | "opus" | "flac" | "aiff" => {
|
"mp3" | "wav" | "ogg" | "opus" | "flac" | "aiff" => {
|
||||||
command =
|
command =
|
||||||
FFMPEGCommand::new(MediaType::Audio, file, size.clone(), codec.clone())
|
FFMPEGCommand::new(MediaType::Audio, file, size, codec.clone()).await?;
|
||||||
.await?;
|
|
||||||
}
|
}
|
||||||
"jpg" | "png" | "webp" | "exr" | "jpeg" | "tiff" | "bpm" | "raw" | "tif" => {
|
"jpg" | "png" | "webp" | "exr" | "jpeg" | "tiff" | "bpm" | "raw" | "tif" => {
|
||||||
command =
|
command =
|
||||||
FFMPEGCommand::new(MediaType::Image, file, size.clone(), codec.clone())
|
FFMPEGCommand::new(MediaType::Image, file, size, codec.clone()).await?;
|
||||||
.await?;
|
|
||||||
}
|
}
|
||||||
"gif" => {
|
"gif" => {
|
||||||
command = FFMPEGCommand::new(
|
command =
|
||||||
MediaType::AnimatedImage,
|
FFMPEGCommand::new(MediaType::AnimatedImage, file, size, codec.clone())
|
||||||
file,
|
|
||||||
size.clone(),
|
|
||||||
codec.clone(),
|
|
||||||
)
|
|
||||||
.await?;
|
.await?;
|
||||||
}
|
}
|
||||||
_ => break,
|
_ => break,
|
||||||
}
|
}
|
||||||
dbg!(&command.command.0);
|
|
||||||
|
|
||||||
command.command.0.stdout(Stdio::piped());
|
command.command.0.stdout(Stdio::piped());
|
||||||
command.command.0.stderr(Stdio::null());
|
command.command.0.stderr(Stdio::null());
|
||||||
|
@ -168,7 +160,7 @@ async fn main() -> anyhow::Result<()> {
|
||||||
'line: while let Ok(Some(line)) = buff_reader.1.next_line().await {
|
'line: while let Ok(Some(line)) = buff_reader.1.next_line().await {
|
||||||
if let Some(time_start) = line.find("out_time=") {
|
if let Some(time_start) = line.find("out_time=") {
|
||||||
let time: Vec<String> = line[time_start + 10..]
|
let time: Vec<String> = line[time_start + 10..]
|
||||||
.split(":")
|
.split(':')
|
||||||
.map(|s| s.to_owned())
|
.map(|s| s.to_owned())
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue