aboutsummaryrefslogtreecommitdiff
path: root/transcoder/src/fragment.rs
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2025-04-16 20:06:01 +0200
committermetamuffin <metamuffin@disroot.org>2025-04-16 20:06:01 +0200
commitd26849375c70c795fdf664f9dfea68c273b6d483 (patch)
tree53ad4f0eff3604e80b27ff0abf0438ea6c69d432 /transcoder/src/fragment.rs
parent1cd966f7454f052fda6c6c9ae1597479f05e23d9 (diff)
parentcdf95d7b80bd2b78895671da8f462145bb5db522 (diff)
downloadjellything-d26849375c70c795fdf664f9dfea68c273b6d483.tar
jellything-d26849375c70c795fdf664f9dfea68c273b6d483.tar.bz2
jellything-d26849375c70c795fdf664f9dfea68c273b6d483.tar.zst
Merge branch 'rewrite-stream'
Diffstat (limited to 'transcoder/src/fragment.rs')
-rw-r--r--transcoder/src/fragment.rs108
1 files changed, 51 insertions, 57 deletions
diff --git a/transcoder/src/fragment.rs b/transcoder/src/fragment.rs
index 8822fa2..88a311e 100644
--- a/transcoder/src/fragment.rs
+++ b/transcoder/src/fragment.rs
@@ -7,7 +7,8 @@
use crate::LOCAL_VIDEO_TRANSCODING_TASKS;
use jellybase::{
cache::{async_cache_file, CachePath},
- common::jhls::EncodingProfile,
+ common::stream::{StreamFormatInfo, TrackKind},
+ CONF,
};
use log::{debug, info};
use std::process::Stdio;
@@ -17,77 +18,70 @@ use tokio::{
};
// TODO odd video resolutions can cause errors when transcoding to YUV42{0,2}
-// TODO with an implementation that cant handle it (SVT-AV1 such an impl).
+// TODO with an implementation that cant handle it (SVT-AV1 is such an impl).
pub async fn transcode(
key: &str,
- enc: &EncodingProfile,
+ kind: TrackKind,
+ format: &StreamFormatInfo,
input: impl FnOnce(ChildStdin),
) -> anyhow::Result<CachePath> {
async_cache_file(
- &["frag-tc", key, &format!("{enc:?}")],
+ &["frag-tc", key, &format!("{format:?}")],
move |mut output| async move {
let _permit = LOCAL_VIDEO_TRANSCODING_TASKS.acquire().await?;
- debug!("transcoding fragment with {enc:?}");
+ debug!("transcoding fragment with {format:?}");
- let mut args = Vec::new();
- match enc {
- EncodingProfile::Video {
- codec,
- preset,
- bitrate,
- width,
- } => {
- if let Some(width) = width {
- args.push("-vf".to_string());
- args.push(format!("scale={width}:-1"));
- }
- args.push("-c:v".to_string());
- args.push(codec.to_string());
- if let Some(preset) = preset {
- args.push("-preset".to_string());
- args.push(format!("{preset}"));
- }
- args.push("-b:v".to_string());
- args.push(format!("{bitrate}"));
- }
- EncodingProfile::Audio {
- codec,
- bitrate,
- sample_rate,
- channels,
- } => {
- if let Some(channels) = channels {
- args.push("-ac".to_string());
- args.push(format!("{channels}"))
- }
- if let Some(sample_rate) = sample_rate {
- args.push("-ar".to_string());
- args.push(format!("{sample_rate}"))
- }
- args.push("-c:a".to_string());
- args.push(codec.to_string());
- args.push("-b:a".to_string());
- args.push(format!("{bitrate}"));
- }
- EncodingProfile::Subtitles { codec } => {
- args.push("-c:s".to_string());
- args.push(codec.to_string());
- }
+ let template = match format.codec.as_str() {
+ "V_MPEG4/ISO/AVC" => CONF.encoders.avc.as_ref(),
+ "V_MPEGH/ISO/HEVC" => CONF.encoders.hevc.as_ref(),
+ "V_VP8" => CONF.encoders.vp8.as_ref(),
+ "V_VP9" => CONF.encoders.vp9.as_ref(),
+ "V_AV1" => CONF.encoders.av1.as_ref(),
+ _ => None,
+ }
+ .or(CONF.encoders.generic.as_ref())
+ .cloned()
+ .unwrap_or("ffmpeg %i %f %e %o".to_owned());
+
+ let filter = match kind {
+ TrackKind::Video => format!("-vf scale={}:-1", format.width.unwrap()),
+ TrackKind::Audio => format!(""),
+ TrackKind::Subtitle => String::new(),
+ };
+ let typechar = match kind {
+ TrackKind::Video => "v",
+ TrackKind::Audio => "a",
+ TrackKind::Subtitle => "s",
+ };
+ let fallback_encoder = match format.codec.as_str() {
+ "A_OPUS" => "libopus",
+ "V_VP8" => "libvpx",
+ "V_VP9" => "libvpx-vp9",
+ "V_AV1" => "libaom", // svtav1 is x86 only :(
+ "V_MPEG4/ISO/AVC" => "libx264",
+ "V_MPEGH/ISO/HEVC" => "libx265",
+ _ => "",
};
- info!("encoding with {:?}", args.join(" "));
- let mut proc = Command::new("ffmpeg")
+ let args = template
+ .replace("%i", "-f matroska -i pipe:0 -copyts")
+ .replace("%o", "-f matroska pipe:1")
+ .replace("%f", &filter)
+ .replace("%e", "-c:%t %c -b:%t %r")
+ .replace("%t", typechar)
+ .replace("%c", fallback_encoder)
+ .replace("%r", &(format.bitrate as i64).to_string())
+ .replace(" ", " ");
+
+ info!("encoding with {:?}", args);
+
+ let mut args = args.split(" ");
+ let mut proc = Command::new(args.next().unwrap())
.stdin(Stdio::piped())
.stdout(Stdio::piped())
- .args(["-f", "matroska", "-i", "pipe:0"])
.args(args)
- .args(["-f", "webm", "pipe:1"])
.spawn()?;
- // let mut proc = Command::new("cat")
- // .stdin(Stdio::piped())
- // .stdout(Stdio::piped())
- // .spawn()?;
let stdin = proc.stdin.take().unwrap();
let mut stdout = proc.stdout.take().unwrap();