add simple mux command

This commit is contained in:
2022-02-26 03:05:34 +05:30
parent e503f60bc3
commit d5343202aa
9 changed files with 200 additions and 4 deletions

2
.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
target/
result

View File

@@ -20,9 +20,10 @@
devShells = with pkgs; {
default = mkShell
{
buildInputs = [
buildInputs = with gst_all_1; [
rust-bin.nightly.latest.default
rust-analyzer
ffmpeg
];
};
bare = mkShell
@@ -47,6 +48,9 @@
nativeBuildInputs = with pkgs; [
rust-bin.nightly.latest.default
];
buildInputs = with pkgs; [
ffmpeg
];
cargoSha256 = "sha256-DhWWUNDpDsao6lOogoM5UfUgrUfEmZvCpY0pxmr4/mI=";
};
}

9
general.rs Normal file
View File

@@ -0,0 +1,9 @@
use serenity::framework::standard::{macros::command, CommandResult};
use serenity::model::prelude::*;
use serenity::prelude::*;
#[command]
pub async fn ping(ctx: &Context, msg: &Message) -> CommandResult {
msg.reply(ctx, "Pong!").await?;
Ok(())
}

9
src/commands/general.rs Normal file
View File

@@ -0,0 +1,9 @@
use serenity::framework::standard::{macros::command, CommandResult};
use serenity::model::prelude::*;
use serenity::prelude::*;
#[command]
pub async fn ping(ctx: &Context, msg: &Message) -> CommandResult {
msg.reply(ctx, "Pong!").await?;
Ok(())
}

2
src/commands/mod.rs Normal file
View File

@@ -0,0 +1,2 @@
pub mod general;
pub mod transcode;

71
src/commands/transcode.rs Normal file
View File

@@ -0,0 +1,71 @@
use crate::lib::ffmpeg::FfmpegTranscode;
use serenity::{
framework::standard::{macros::command, Args, CommandResult},
http::AttachmentType,
model::prelude::*,
prelude::*,
};
use std::{fs::remove_file, path::Path, process::ExitStatus};
use tokio::fs::File;
#[command]
#[aliases("mux")]
pub async fn remux(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
let q: Vec<&str> = args.raw().collect::<Vec<&str>>();
if q.len() < 2 || q.len() > 4 {
msg.reply(
ctx,
"Please use the proper syntax: `xxremux <audio> <video> [audio_codec] [video_codec]` or attach something",
)
.await?;
return Ok(());
}
let mut trans = FfmpegTranscode::default();
trans.add_input(q[0]).add_input(q[1]);
if q.len() > 2 {
trans.set_acodec(q[2]);
}
if q.len() > 3 {
trans.set_vcodec(q[3]);
}
let ext = Path::new(&q[1]).extension().unwrap().to_str().unwrap();
let output = format!("/tmp/{}{}.{}", "singh4-", msg.id, ext);
trans
.add_flag("shortest")
.set_output(&output)
.add_arg("map", "0:a:0")
.add_arg("map", "1:v:0");
let mut m = msg.reply_ping(ctx, "Working").await?;
let exit_code: ExitStatus = trans.run();
let file: File = File::open(&output).await?;
if !exit_code.success() {
msg.reply(ctx, "Some error occurred, please check the inputs")
.await?;
} else if file.metadata().await.unwrap().len() > 8 * 1024 * 1024 {
msg.reply(ctx, "Output file larger than 8 MB").await?;
} else {
m.edit(ctx, |m| m.content("Uploading")).await?;
msg.channel_id
.send_message(ctx, |m| {
m.add_file(AttachmentType::File {
file: &file,
filename: format!("{}.{}", msg.id, ext),
})
.content(msg.author.mention())
})
.await?;
m.delete(ctx).await?;
}
remove_file(output)?;
Ok(())
}

84
src/lib/ffmpeg.rs Normal file
View File

@@ -0,0 +1,84 @@
use std::process::{Command, ExitStatus};
//Helper lib for running ffmpeg using std::process::Command
fn sanitize_arg<V: Into<String>>(value: V) -> String {
let v: String = value.into();
if v.starts_with('-') {
v
} else {
format!("-{}", v)
}
}
#[derive(Clone, Debug)]
pub struct FfmpegTranscode {
args: Vec<String>,
out: String,
acodec: String,
vcodec: String,
}
impl Default for FfmpegTranscode {
fn default() -> Self {
FfmpegTranscode {
args: vec![],
out: String::from("/tmp/ffmpeg"),
acodec: String::from("copy"),
vcodec: String::from("copy"),
}
}
}
impl FfmpegTranscode {
pub fn add_flag<V: Into<String>>(&mut self, value: V) -> &mut Self {
self.args.push(sanitize_arg(value));
self
}
pub fn add_flags<T: Into<String>, V: IntoIterator<Item = T>>(&mut self, value: V) -> &mut Self {
for v in value {
self.add_flag(v);
}
self
}
pub fn add_arg<K: Into<String>, V: ToString>(&mut self, key: K, value: V) -> &mut Self {
self.args.push(sanitize_arg(key));
self.args.push(value.to_string());
self
}
pub fn add_input<V: ToString>(&mut self, input: V) -> &mut Self {
self.add_arg('i', input)
}
pub fn set_output<V: ToString>(&mut self, output: V) -> &mut Self {
self.out = output.to_string();
self
}
pub fn set_acodec<V: ToString>(&mut self, acodec: V) -> &mut Self {
self.acodec = acodec.to_string();
self
}
pub fn set_vcodec<V: ToString>(&mut self, vcodec: V) -> &mut Self {
self.vcodec = vcodec.to_string();
self
}
pub fn add_map(&mut self, inp: i32, s: char, out: i32) -> &mut Self {
self.add_arg("map", format!("{}:{}:{}", inp, s, out))
}
pub fn run(&self) -> ExitStatus {
Command::new("ffmpeg")
.args(&self.args)
.args(vec!["-c:a", &self.acodec])
.args(vec!["-c:v", &self.vcodec])
.arg(&self.out)
.status()
.expect("FFmpeg failed to run")
}
}

1
src/lib/mod.rs Normal file
View File

@@ -0,0 +1 @@
pub mod ffmpeg;

View File

@@ -1,11 +1,15 @@
mod commands;
mod handler;
mod lib;
use commands::general::*;
use commands::transcode::*;
use handler::Handler;
use serenity::{
client::bridge::gateway::ShardManager,
framework::{
standard::{
help_commands,
macros::help,
macros::{group, help},
Args, CommandGroup, CommandResult, HelpOptions,
},
StandardFramework,
@@ -22,6 +26,14 @@ impl TypeMapKey for ShardManagerContainer {
type Value = Arc<Mutex<ShardManager>>;
}
#[group]
#[commands(remux)]
struct Transcode;
#[group]
#[commands(ping)]
struct General;
#[help]
#[max_levenshtein_distance(2)]
#[indention_prefix = "+"]
@@ -56,8 +68,10 @@ async fn main() {
};
let framework = StandardFramework::new()
.configure(|c| c.owners(owners).prefix(","))
.help(&MY_HELP);
.configure(|c| c.owners(owners).prefix("xx"))
.help(&MY_HELP)
.group(&GENERAL_GROUP)
.group(&TRANSCODE_GROUP);
let mut client = Client::builder(&token)
.framework(framework)