mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-06-01 04:34:50 -04:00
Fix mediainfo number parsing
This commit is contained in:
parent
64d4ee9168
commit
dbe85322ea
@ -11,7 +11,7 @@ COPY src src
|
|||||||
RUN cargo install --path .
|
RUN cargo install --path .
|
||||||
|
|
||||||
FROM alpine
|
FROM alpine
|
||||||
RUN apk add --no-cache ffmpeg
|
RUN apk add --no-cache ffmpeg mediainfo
|
||||||
COPY --from=builder /usr/local/cargo/bin/transcoder ./transcoder
|
COPY --from=builder /usr/local/cargo/bin/transcoder ./transcoder
|
||||||
|
|
||||||
EXPOSE 7666
|
EXPOSE 7666
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
FROM rust:alpine
|
FROM rust:alpine
|
||||||
RUN apk add --no-cache musl-dev ffmpeg
|
RUN apk add --no-cache musl-dev ffmpeg mediainfo
|
||||||
RUN cargo install cargo-watch
|
RUN cargo install cargo-watch
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
|
use json::JsonValue;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use std::str;
|
use std::str::{self, FromStr};
|
||||||
use tokio::process::Command;
|
use tokio::process::Command;
|
||||||
use utoipa::ToSchema;
|
use utoipa::ToSchema;
|
||||||
|
|
||||||
@ -65,20 +66,26 @@ pub async fn identify(path: String) -> Result<MediaInfo, std::io::Error> {
|
|||||||
.arg("--Language=raw")
|
.arg("--Language=raw")
|
||||||
.arg(path)
|
.arg(path)
|
||||||
.output()
|
.output()
|
||||||
.await?;
|
.await
|
||||||
|
.expect("Error running the mediainfo command");
|
||||||
assert!(mediainfo.status.success());
|
assert!(mediainfo.status.success());
|
||||||
let output = json::parse(str::from_utf8(mediainfo.stdout.as_slice()).unwrap()).unwrap();
|
let output = json::parse(str::from_utf8(mediainfo.stdout.as_slice()).unwrap()).unwrap();
|
||||||
|
|
||||||
let general = output["media"]["tracks"]
|
let general = output["media"]["track"]
|
||||||
.members()
|
.members()
|
||||||
.find(|x| x["@type"] == "General")
|
.find(|x| x["@type"] == "General")
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
fn parse<F: FromStr>(v: &JsonValue) -> Option<F> {
|
||||||
|
v.as_str().and_then(|x| x.parse::<F>().ok())
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Every number is wrapped by "" in mediainfo json's mode so the number parsing is wrong.
|
||||||
Ok(MediaInfo {
|
Ok(MediaInfo {
|
||||||
length: general["Duration"].as_f32().unwrap(),
|
length: parse::<f32>(&general["Duration"]).unwrap(),
|
||||||
container: general["Format"].as_str().unwrap().to_string(),
|
container: general["Format"].as_str().unwrap().to_string(),
|
||||||
video: {
|
video: {
|
||||||
let v = output["media"]["tracks"]
|
let v = output["media"]["track"]
|
||||||
.members()
|
.members()
|
||||||
.find(|x| x["@type"] == "Video")
|
.find(|x| x["@type"] == "Video")
|
||||||
.expect("File without video found. This is not supported");
|
.expect("File without video found. This is not supported");
|
||||||
@ -86,17 +93,17 @@ pub async fn identify(path: String) -> Result<MediaInfo, std::io::Error> {
|
|||||||
// This codec is not in the right format (does not include bitdepth...).
|
// This codec is not in the right format (does not include bitdepth...).
|
||||||
codec: v["Format"].as_str().unwrap().to_string(),
|
codec: v["Format"].as_str().unwrap().to_string(),
|
||||||
language: v["Language"].as_str().map(|x| x.to_string()),
|
language: v["Language"].as_str().map(|x| x.to_string()),
|
||||||
quality: Quality::from_height(v["Height"].as_u32().unwrap()),
|
quality: Quality::from_height(parse::<u32>(&v["Height"]).unwrap()),
|
||||||
width: v["Width"].as_u32().unwrap(),
|
width: parse::<u32>(&v["Width"]).unwrap(),
|
||||||
height: v["Height"].as_u32().unwrap(),
|
height: parse::<u32>(&v["Height"]).unwrap(),
|
||||||
bitrate: v["BitRate"].as_u32().unwrap(),
|
bitrate: parse::<u32>(&v["BitRate"]).unwrap(),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
audios: output["media"]["tracks"]
|
audios: output["media"]["track"]
|
||||||
.members()
|
.members()
|
||||||
.filter(|x| x["@type"] == "Audio")
|
.filter(|x| x["@type"] == "Audio")
|
||||||
.map(|a| Track {
|
.map(|a| Track {
|
||||||
index: a["StreamOrder"].as_u32().unwrap(),
|
index: parse::<u32>(&a["StreamOrder"]).unwrap(),
|
||||||
title: a["Title"].as_str().map(|x| x.to_string()),
|
title: a["Title"].as_str().map(|x| x.to_string()),
|
||||||
language: a["Language"].as_str().map(|x| x.to_string()),
|
language: a["Language"].as_str().map(|x| x.to_string()),
|
||||||
// TODO: format is invalid. Channels count missing...
|
// TODO: format is invalid. Channels count missing...
|
||||||
@ -105,11 +112,11 @@ pub async fn identify(path: String) -> Result<MediaInfo, std::io::Error> {
|
|||||||
forced: a["Forced"] == "No",
|
forced: a["Forced"] == "No",
|
||||||
})
|
})
|
||||||
.collect(),
|
.collect(),
|
||||||
subtitles: output["media"]["tracks"]
|
subtitles: output["media"]["track"]
|
||||||
.members()
|
.members()
|
||||||
.filter(|x| x["@type"] == "Text")
|
.filter(|x| x["@type"] == "Text")
|
||||||
.map(|a| Track {
|
.map(|a| Track {
|
||||||
index: a["StreamOrder"].as_u32().unwrap(),
|
index: parse::<u32>(&a["StreamOrder"]).unwrap(),
|
||||||
title: a["Title"].as_str().map(|x| x.to_string()),
|
title: a["Title"].as_str().map(|x| x.to_string()),
|
||||||
language: a["Language"].as_str().map(|x| x.to_string()),
|
language: a["Language"].as_str().map(|x| x.to_string()),
|
||||||
// TODO: format is invalid. Channels count missing...
|
// TODO: format is invalid. Channels count missing...
|
||||||
@ -119,7 +126,7 @@ pub async fn identify(path: String) -> Result<MediaInfo, std::io::Error> {
|
|||||||
})
|
})
|
||||||
.collect(),
|
.collect(),
|
||||||
fonts: vec![],
|
fonts: vec![],
|
||||||
chapters: output["media"]["tracks"]
|
chapters: output["media"]["track"]
|
||||||
.members()
|
.members()
|
||||||
.find(|x| x["@type"] == "Menu")
|
.find(|x| x["@type"] == "Menu")
|
||||||
.map(|x| {
|
.map(|x| {
|
||||||
|
@ -94,7 +94,7 @@ async fn identify_resource(
|
|||||||
.map_err(|_| ApiError::NotFound)?;
|
.map_err(|_| ApiError::NotFound)?;
|
||||||
|
|
||||||
identify(path).await.map(|info| Json(info)).map_err(|e| {
|
identify(path).await.map(|info| Json(info)).map_err(|e| {
|
||||||
eprintln!("Unhandled error occured while transcoding: {}", e);
|
eprintln!("Unhandled error occured while identifing the resource: {}", e);
|
||||||
ApiError::InternalError
|
ApiError::InternalError
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -98,7 +98,7 @@ impl Quality {
|
|||||||
|
|
||||||
pub fn from_height(height: u32) -> Self {
|
pub fn from_height(height: u32) -> Self {
|
||||||
Self::iter()
|
Self::iter()
|
||||||
.find(|x| x.height() <= height)
|
.find(|x| x.height() >= height)
|
||||||
.unwrap_or(&Quality::P240)
|
.unwrap_or(&Quality::P240)
|
||||||
.clone()
|
.clone()
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user