Files
clipbin-desktop/crates/clipbin-core/src/segments.rs
T
harry 435ddf2b17 feat: automatically record Steam game sessions
Detect games with native process exit watchers, own OBS on a background worker, and persist settings and recoverable session timelines. Place segments by split frame counts, recover capture with honest gaps, and finalise on game exit or explicit Quit.

Keep the current recording alive after GPUI closes its last window, then exit when the game ends. Add an end-to-end rig covering recording, recovery, exact packet-count offsets, disk library reload and clean Quit.
2026-10-08 17:30:40 +02:00

31 lines
1.0 KiB
Rust

//! A split racing with stop can leave only a Matroska header, with no footage.
use std::{
fs::File,
io::{self, Read},
path::Path,
};
/// The pinned muxer writes its first Cluster immediately after a small header.
/// Inspect only that prefix, so checking a completed segment never reads its footage.
pub fn has_cluster(path: &Path) -> io::Result<bool> {
cluster_in(File::open(path)?)
}
fn cluster_in(reader: impl Read) -> io::Result<bool> {
let mut prefix = Vec::new();
reader.take(64 * 1024).read_to_end(&mut prefix)?;
Ok(prefix.windows(4).any(|id| id == [0x1f, 0x43, 0xb6, 0x75]))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn distinguishes_a_header_only_tail_from_media() {
let header = [0x1a, 0x45, 0xdf, 0xa3, 0x80, 0x18, 0x53, 0x80, 0x67, 0xff];
assert!(!cluster_in(header.as_slice()).unwrap());
let mut media = header.to_vec();
media.extend([0x1f, 0x43, 0xb6, 0x75, 0x84, 0xe7, 0x82, 0, 0]);
assert!(cluster_in(media.as_slice()).unwrap());
}
}