diff --git a/Cargo.lock b/Cargo.lock
index 55fb935..376544f 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2744,6 +2744,13 @@ dependencies = [
"windows-sys 0.52.0",
]
+[[package]]
+name = "sort_perf_log"
+version = "0.1.0"
+dependencies = [
+ "regex",
+]
+
[[package]]
name = "spki"
version = "0.6.0"
diff --git a/Cargo.toml b/Cargo.toml
index c6f0356..8c592cc 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -12,6 +12,7 @@ members = [
"find_log_processtime",
"archive_dirs",
"s3_bucket_downloader",
+ "sort_perf_log",
# Add other tools here
]
resolver = "2"
diff --git a/copy_random_files/Cargo.lock b/copy_random_files/Cargo.lock
new file mode 100644
index 0000000..46c527d
--- /dev/null
+++ b/copy_random_files/Cargo.lock
@@ -0,0 +1,408 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "anstream"
+version = "0.6.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b"
+dependencies = [
+ "anstyle",
+ "anstyle-parse",
+ "anstyle-query",
+ "anstyle-wincon",
+ "colorchoice",
+ "is_terminal_polyfill",
+ "utf8parse",
+]
+
+[[package]]
+name = "anstyle"
+version = "1.0.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9"
+
+[[package]]
+name = "anstyle-parse"
+version = "0.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9"
+dependencies = [
+ "utf8parse",
+]
+
+[[package]]
+name = "anstyle-query"
+version = "1.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c"
+dependencies = [
+ "windows-sys 0.59.0",
+]
+
+[[package]]
+name = "anstyle-wincon"
+version = "3.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125"
+dependencies = [
+ "anstyle",
+ "windows-sys 0.59.0",
+]
+
+[[package]]
+name = "byteorder"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "clap"
+version = "4.5.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8"
+dependencies = [
+ "clap_builder",
+ "clap_derive",
+]
+
+[[package]]
+name = "clap_builder"
+version = "4.5.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54"
+dependencies = [
+ "anstream",
+ "anstyle",
+ "clap_lex",
+ "strsim",
+]
+
+[[package]]
+name = "clap_derive"
+version = "4.5.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab"
+dependencies = [
+ "heck",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "clap_lex"
+version = "0.7.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97"
+
+[[package]]
+name = "colorchoice"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990"
+
+[[package]]
+name = "console"
+version = "0.15.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb"
+dependencies = [
+ "encode_unicode",
+ "lazy_static",
+ "libc",
+ "unicode-width",
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "copy_random_files"
+version = "0.1.0"
+dependencies = [
+ "clap",
+ "indicatif",
+ "rand",
+]
+
+[[package]]
+name = "encode_unicode"
+version = "0.3.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
+
+[[package]]
+name = "getrandom"
+version = "0.2.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "wasi",
+]
+
+[[package]]
+name = "heck"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
+
+[[package]]
+name = "indicatif"
+version = "0.17.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "763a5a8f45087d6bcea4222e7b72c291a054edf80e4ef6efd2a4979878c7bea3"
+dependencies = [
+ "console",
+ "instant",
+ "number_prefix",
+ "portable-atomic",
+ "unicode-width",
+]
+
+[[package]]
+name = "instant"
+version = "0.1.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "is_terminal_polyfill"
+version = "1.70.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
+
+[[package]]
+name = "lazy_static"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
+
+[[package]]
+name = "libc"
+version = "0.2.161"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1"
+
+[[package]]
+name = "number_prefix"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3"
+
+[[package]]
+name = "portable-atomic"
+version = "1.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cc9c68a3f6da06753e9335d63e27f6b9754dd1920d941135b7ea8224f141adb2"
+
+[[package]]
+name = "ppv-lite86"
+version = "0.2.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04"
+dependencies = [
+ "zerocopy",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.89"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.37"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "rand"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
+dependencies = [
+ "libc",
+ "rand_chacha",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_chacha"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
+dependencies = [
+ "ppv-lite86",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.6.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
+dependencies = [
+ "getrandom",
+]
+
+[[package]]
+name = "strsim"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
+
+[[package]]
+name = "syn"
+version = "2.0.87"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe"
+
+[[package]]
+name = "unicode-width"
+version = "0.1.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af"
+
+[[package]]
+name = "utf8parse"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
+
+[[package]]
+name = "wasi"
+version = "0.11.0+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
+
+[[package]]
+name = "windows-sys"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
+dependencies = [
+ "windows-targets",
+]
+
+[[package]]
+name = "windows-sys"
+version = "0.59.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
+dependencies = [
+ "windows-targets",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
+dependencies = [
+ "windows_aarch64_gnullvm",
+ "windows_aarch64_msvc",
+ "windows_i686_gnu",
+ "windows_i686_gnullvm",
+ "windows_i686_msvc",
+ "windows_x86_64_gnu",
+ "windows_x86_64_gnullvm",
+ "windows_x86_64_msvc",
+]
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
+
+[[package]]
+name = "windows_i686_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
+
+[[package]]
+name = "zerocopy"
+version = "0.7.35"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
+dependencies = [
+ "byteorder",
+ "zerocopy-derive",
+]
+
+[[package]]
+name = "zerocopy-derive"
+version = "0.7.35"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
diff --git a/sort_perf_log/CLAUDE.md b/sort_perf_log/CLAUDE.md
new file mode 100644
index 0000000..68ee27c
--- /dev/null
+++ b/sort_perf_log/CLAUDE.md
@@ -0,0 +1,11 @@
+
+# Recent Activity
+
+
+
+### Jan 14, 2026
+
+| ID | Time | T | Title | Read |
+|----|------|---|-------|------|
+| #1214 | 7:00 PM | 🟣 | Rust Implementation Started for Performance Log Parser | ~300 |
+
diff --git a/sort_perf_log/Cargo.toml b/sort_perf_log/Cargo.toml
new file mode 100644
index 0000000..ec1247c
--- /dev/null
+++ b/sort_perf_log/Cargo.toml
@@ -0,0 +1,12 @@
+[package]
+name = "sort_perf_log"
+version = "0.1.0"
+edition = "2021"
+description = "Parse and sort video processing performance logs by total processing time"
+
+[dependencies]
+regex = "1"
+
+[profile.release]
+opt-level = 3
+lto = true
diff --git a/sort_perf_log/src/CLAUDE.md b/sort_perf_log/src/CLAUDE.md
new file mode 100644
index 0000000..b9f2e10
--- /dev/null
+++ b/sort_perf_log/src/CLAUDE.md
@@ -0,0 +1,12 @@
+
+# Recent Activity
+
+
+
+### Jan 14, 2026
+
+| ID | Time | T | Title | Read |
+|----|------|---|-------|------|
+| #1216 | 7:09 PM | ✅ | Applied automated Rust code formatting across project | ~256 |
+| #1215 | " | 🔴 | Fixed cargo fmt formatting violations in Rust CLI tool | ~312 |
+
diff --git a/sort_perf_log/src/main.rs b/sort_perf_log/src/main.rs
new file mode 100644
index 0000000..f732600
--- /dev/null
+++ b/sort_perf_log/src/main.rs
@@ -0,0 +1,221 @@
+use regex::Regex;
+use std::collections::HashMap;
+use std::env;
+use std::fs;
+use std::io::{self, BufRead, Write};
+
+#[derive(Default, Debug)]
+struct VideoMetrics {
+ scene_detect_fps: Option,
+ scene_detect_time: Option,
+ ocr_fps: Option,
+ ocr_time: Option,
+ logo_detect_images: Option,
+ logo_detect_fps: Option,
+ logo_detect_time: Option,
+ object_detect_images: Option,
+ object_detect_fps: Option,
+ object_detect_time: Option,
+ transcribe_time: Option,
+ scene_description_time: Option,
+ process_video_time: Option,
+}
+
+fn fmt_float(val: Option, suffix: &str) -> String {
+ match val {
+ Some(v) => format!("{:.1}{}", v, suffix),
+ None => "-".to_string(),
+ }
+}
+
+fn fmt_int(val: Option) -> String {
+ match val {
+ Some(v) => v.to_string(),
+ None => "-".to_string(),
+ }
+}
+
+fn main() -> io::Result<()> {
+ let args: Vec = env::args().collect();
+
+ if args.len() < 3 {
+ eprintln!("Usage: {} ", args[0]);
+ eprintln!(
+ "Example: {} 20260113-all-perf.log 20260113-all-perf-sorted.log",
+ args[0]
+ );
+ std::process::exit(1);
+ }
+
+ let input_file = &args[1];
+ let output_file = &args[2];
+
+ // Compile regex patterns
+ let summary_re = Regex::new(r"Performance Summary of (input_files/\S+):").unwrap();
+ let scene_detect_re =
+ Regex::new(r"func=scene_detect\s+file=\S+\s+fps=([\d.]+)\s+time=([\d.]+)s").unwrap();
+ let ocr_re = Regex::new(r"func=ocr\s+file=\S+\s+fps=([\d.]+)\s+time=([\d.]+)s").unwrap();
+ let logo_detect_re =
+ Regex::new(r"func=logo_detect\s+images=(\d+)\s+fps=([\d.]+)\s+time=([\d.]+)s").unwrap();
+ let object_detect_re =
+ Regex::new(r"func=object_detect\s+images=(\d+)\s+fps=([\d.]+)\s+time=([\d.]+)s").unwrap();
+ let transcribe_re = Regex::new(r"func=transcribe\s+file=\S+\s+time=([\d.]+)s").unwrap();
+ let scene_desc_re = Regex::new(r"func=scene_description\s+file=\S+\s+time=([\d.]+)s").unwrap();
+ let process_video_re = Regex::new(r"func=process_video\s+file=\S+\s+time=([\d.]+)s").unwrap();
+
+ // Parse the log file
+ let file = fs::File::open(input_file)?;
+ let reader = io::BufReader::new(file);
+
+ let mut videos: HashMap = HashMap::new();
+ let mut current_video: Option = None;
+
+ for line in reader.lines() {
+ let line = line?;
+
+ // Check for Performance Summary line
+ if let Some(caps) = summary_re.captures(&line) {
+ let full_path = caps.get(1).unwrap().as_str();
+ let video_id = full_path.replace("input_files/", "");
+ current_video = Some(video_id.clone());
+ videos.entry(video_id).or_default();
+ continue;
+ }
+
+ // Parse performance metrics
+ if let Some(ref video_id) = current_video {
+ if !line.contains("[PERF]") {
+ continue;
+ }
+
+ let metrics = videos.get_mut(video_id).unwrap();
+
+ if let Some(caps) = scene_detect_re.captures(&line) {
+ metrics.scene_detect_fps = caps.get(1).and_then(|m| m.as_str().parse().ok());
+ metrics.scene_detect_time = caps.get(2).and_then(|m| m.as_str().parse().ok());
+ continue;
+ }
+
+ if let Some(caps) = ocr_re.captures(&line) {
+ metrics.ocr_fps = caps.get(1).and_then(|m| m.as_str().parse().ok());
+ metrics.ocr_time = caps.get(2).and_then(|m| m.as_str().parse().ok());
+ continue;
+ }
+
+ if let Some(caps) = logo_detect_re.captures(&line) {
+ metrics.logo_detect_images = caps.get(1).and_then(|m| m.as_str().parse().ok());
+ metrics.logo_detect_fps = caps.get(2).and_then(|m| m.as_str().parse().ok());
+ metrics.logo_detect_time = caps.get(3).and_then(|m| m.as_str().parse().ok());
+ continue;
+ }
+
+ if let Some(caps) = object_detect_re.captures(&line) {
+ metrics.object_detect_images = caps.get(1).and_then(|m| m.as_str().parse().ok());
+ metrics.object_detect_fps = caps.get(2).and_then(|m| m.as_str().parse().ok());
+ metrics.object_detect_time = caps.get(3).and_then(|m| m.as_str().parse().ok());
+ continue;
+ }
+
+ if let Some(caps) = transcribe_re.captures(&line) {
+ metrics.transcribe_time = caps.get(1).and_then(|m| m.as_str().parse().ok());
+ continue;
+ }
+
+ if let Some(caps) = scene_desc_re.captures(&line) {
+ metrics.scene_description_time = caps.get(1).and_then(|m| m.as_str().parse().ok());
+ continue;
+ }
+
+ if let Some(caps) = process_video_re.captures(&line) {
+ metrics.process_video_time = caps.get(1).and_then(|m| m.as_str().parse().ok());
+ continue;
+ }
+ }
+ }
+
+ // Sort videos by process_video_time (descending)
+ let mut sorted_videos: Vec<(&String, &VideoMetrics)> = videos
+ .iter()
+ .filter(|(_, m)| m.process_video_time.is_some())
+ .collect();
+
+ sorted_videos.sort_by(|a, b| {
+ b.1.process_video_time
+ .partial_cmp(&a.1.process_video_time)
+ .unwrap_or(std::cmp::Ordering::Equal)
+ });
+
+ // Generate output
+ let mut output = fs::File::create(output_file)?;
+
+ writeln!(
+ output,
+ "# Video Processing Performance Report (Sorted by Total Time)"
+ )?;
+ writeln!(output)?;
+ writeln!(output, "Total videos processed: {}", sorted_videos.len())?;
+ writeln!(output)?;
+ writeln!(output, "| # | Video ID | scene_detect (fps/time) | ocr (fps/time) | logo_detect (imgs/fps/time) | object_detect (imgs/fps/time) | transcribe | scene_desc | total |")?;
+ writeln!(output, "|---|----------|-------------------------|----------------|------------------------------|-------------------------------|------------|------------|-------|")?;
+
+ for (i, (vid, data)) in sorted_videos.iter().enumerate() {
+ let scene_d = format!(
+ "{}/{}",
+ fmt_float(data.scene_detect_fps, ""),
+ fmt_float(data.scene_detect_time, "s")
+ );
+ let ocr = format!(
+ "{}/{}",
+ fmt_float(data.ocr_fps, ""),
+ fmt_float(data.ocr_time, "s")
+ );
+ let logo = format!(
+ "{}/{}/{}",
+ fmt_int(data.logo_detect_images),
+ fmt_float(data.logo_detect_fps, ""),
+ fmt_float(data.logo_detect_time, "s")
+ );
+ let obj = format!(
+ "{}/{}/{}",
+ fmt_int(data.object_detect_images),
+ fmt_float(data.object_detect_fps, ""),
+ fmt_float(data.object_detect_time, "s")
+ );
+ let trans = fmt_float(data.transcribe_time, "s");
+ let scene_desc = fmt_float(data.scene_description_time, "s");
+ let total = fmt_float(data.process_video_time, "s");
+
+ writeln!(
+ output,
+ "| {} | {} | {} | {} | {} | {} | {} | {} | {} |",
+ i + 1,
+ vid,
+ scene_d,
+ ocr,
+ logo,
+ obj,
+ trans,
+ scene_desc,
+ total
+ )?;
+ }
+
+ println!("Output written to {}", output_file);
+ println!("Total videos: {}", sorted_videos.len());
+ if let Some((first_vid, first_data)) = sorted_videos.first() {
+ println!(
+ "Longest: {} at {:.1}s",
+ first_vid,
+ first_data.process_video_time.unwrap_or(0.0)
+ );
+ }
+ if let Some((last_vid, last_data)) = sorted_videos.last() {
+ println!(
+ "Shortest: {} at {:.1}s",
+ last_vid,
+ last_data.process_video_time.unwrap_or(0.0)
+ );
+ }
+
+ Ok(())
+}