Expand description

needle

needle detects openings/intros and endings/credits across video files. needle can be used standalone via a dedicated CLI, or as a library to implement higher-level tools or plugins (e.g., for intro skipping).

The library exposes two central structs:

  1. Analyzer: Decodes one or more videos and converts them into a set of FrameHashes.
  2. Comparator: Searches for openings and endings across two or more videos.

Basic Usage

First, you need to create and run an Analyzer.

This will decode the audio streams for all provided video files and return a list of FrameHashes, one per video. The structure stores a compressed representation of the audio stream that contains only the data we need to search for openings and endings.

use std::path::PathBuf;
use needle::audio::Analyzer;

let video_paths: Vec<PathBuf> = get_sample_paths();
let analyzer = Analyzer::from_files(video_paths, false, false);

// Use a `hash_period` of 1.0, `hash_duration` of 3.0, do not `persist` frame hash data
// and enable `threading`.
let frame_hashes = analyzer.run(1.0, 3.0, false, true).unwrap();

Now you need to create and run a Comparator using the output FrameHashes. You can re-use the videos by constructing an instance from the Analyzer.

use std::path::PathBuf;
use needle::audio::Comparator;

let comparator: Comparator = analyzer.into();
let results = comparator.run_with_frame_hashes(frame_hashes, true, false, false, true).unwrap();

dbg!(results);
// {
//     "/tmp/land-of-lustrous-ep1.mkv": SearchResult {
//         opening: None,
//         ending: Some(
//             (
//                 1331.664387072s,
//                 1419.024930474s,
//             ),
//         ),
//     },
//     "/tmp/land-of-lustrous-ep2.mkv": SearchResult {
//         opening: Some(
//             (
//                 44.718820458s,
//                 131.995463634s,
//             ),
//         ),
//         ending: Some(
//             (
//                 1331.664387072s,
//                 1436.560077708s,
//             ),
//         ),
//     },
//     "/tmp/land-of-lustrous-ep3.mkv": SearchResult {
//         opening: Some(
//             (
//                 41.11111074s,
//                 127.800452334s,
//             ),
//         ),
//         ending: Some(
//             (
//                 1331.664387072s,
//                 1436.560077708s,
//             ),
//         ),
//     },
// },

Comparator::run_with_frame_hashes runs a search for openings and endings using the provided frame hash data. Note that there is an equivalent method that can read existing frame hash data files from disk (Comparator::run).

The output of this method is a map from each video file to a SearchResult. This structure contains the actual times for any detected openings and endings.

Modules

Detects opening and endings across videos using just audio streams.

Common utility functions.

Enums

Common error type.

Type Definitions

Common result type.