diff options
Diffstat (limited to 'import/src/plugins/media_info.rs')
| -rw-r--r-- | import/src/plugins/media_info.rs | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/import/src/plugins/media_info.rs b/import/src/plugins/media_info.rs new file mode 100644 index 0000000..1d4d627 --- /dev/null +++ b/import/src/plugins/media_info.rs @@ -0,0 +1,92 @@ +/* + This file is part of jellything (https://codeberg.org/metamuffin/jellything) + which is licensed under the GNU Affero General Public License (version 3); see /COPYING. + Copyright (C) 2025 metamuffin <metamuffin.org> +*/ + +use crate::plugins::{ImportContext, ImportPlugin}; +use anyhow::{Result, anyhow}; +use jellycommon::{Chapter, NodeID, SourceTrack, SourceTrackKind, TrackSource}; +use jellyremuxer::matroska::Segment; +use std::path::Path; + +pub struct MediaInfo; +impl ImportPlugin for MediaInfo { + fn media(&self, ct: &ImportContext, node: NodeID, path: &Path, seg: &Segment) -> Result<()> { + let tracks = seg + .tracks + .as_ref() + .ok_or(anyhow!("no tracks"))? + .entries + .iter() + .map(|track| SourceTrack { + codec: track.codec_id.clone(), + language: track.language.clone(), + name: track.name.clone().unwrap_or_default(), + federated: Vec::new(), + kind: if let Some(video) = &track.video { + SourceTrackKind::Video { + width: video.pixel_width, + height: video.pixel_height, + fps: video.frame_rate, + } + } else if let Some(audio) = &track.audio { + SourceTrackKind::Audio { + channels: audio.channels as usize, + sample_rate: audio.sampling_frequency, + bit_depth: audio.bit_depth.map(|r| r as usize), + } + } else { + SourceTrackKind::Subtitle + }, + source: TrackSource::Local(path.to_owned(), track.track_number), + }) + .collect::<Vec<_>>(); + + let size = path.metadata()?.len(); + + ct.db.update_node_init(node, |node| { + node.storage_size = size; + node.media = Some(jellycommon::MediaInfo { + chapters: seg + .chapters + .clone() + .map(|c| { + let mut chaps = Vec::new(); + if let Some(ee) = c.edition_entries.first() { + for ca in &ee.chapter_atoms { + let mut labels = Vec::new(); + for cd in &ca.displays { + for lang in &cd.languages { + labels.push((lang.to_owned(), cd.string.clone())) + } + } + chaps.push(Chapter { + labels, + time_start: Some(ca.time_start as f64 * 1e-9), + time_end: ca.time_end.map(|ts| ts as f64 * 1e-9), + }) + } + } + chaps + }) + .unwrap_or_default(), + duration: fix_invalid_runtime( + seg.info.duration.unwrap_or_default() * seg.info.timestamp_scale as f64 * 1e-9, + ), + tracks, + }); + Ok(()) + })?; + + Ok(()) + } +} + +fn fix_invalid_runtime(d: f64) -> f64 { + match d { + // Broken durations found experimentally + 359999.999 | 359999.000 | 86399.999 | 86399.99900000001 => 0., + x => x, + } +} |