AdSlicer Help
_
β–‘
βœ•
🏠
πŸ’Ώ Installation
β–Ά Quick Start
βš™ How It Works
β˜… Tips & Tricks
πŸ’‘ Use Cases
πŸ–¨ Print
Contents
Getting Started
Reference
Guides

AdSlicer

Archival Boundary Detection & Segment Slicing β€” Help Documentation

AdSlicer is an archival boundary-detection and segment-slicing application built for long-form VHS captures, analog transfers, and TV recordings. It analyzes candidate boundaries, identifies likely commercial blocks, and prepares a reviewable export plan that outputs:

  • A clean show file (ads removed)
  • A folder of isolated commercial clips
  • Full diagnostic logs in JSON, CSV, and EDL
  • ffmeta chapter markers for media player navigation
  • A structured ML dataset (dataset.jsonl) with 74 per-segment feature columns
  • A run manifest recording all parameters and detection statistics

The pipeline is self-contained (ffmpeg bundled), batch-friendly, and designed for noisy analog sources where black slugs vary in length and clarity.

Topics

πŸ’ΏInstallation β€” Download a compiled application or build AdSlicer yourself
β˜…Tips & Tricks β€” Practical advice for faster review and safer exports
βœ‚οΈHow It Works β€” Detection pipeline, confidence scoring, export modes
β–ΆQuick Start β€” Get from launch to a clean show master
πŸ”§All Parameters β€” Complete parameter reference
πŸ’ΎPreset System β€” Built-in presets, saving, and file format
πŸŽ›Tuning Guide β€” Fixing false positives, missed breaks, noisy tape
πŸ“ŠML Dataset Output β€” The 74-column dataset.jsonl format
πŸ’‘Use Cases β€” Archiving, batch processing, ML, compilations

Installation

There are two supported ways to install AdSlicer. Most users should download a compiled release. Developers, contributors, and users who need a custom build can compile the application from source.

DEVELOPER

Build AdSlicer Yourself

Clone the repository, install the Rust/Tauri requirements, prepare the bundled media binaries, and build the target for your platform.

  • Useful for development and custom modifications
  • Produces platform-native application bundles
  • Requires Rust, Cargo, Tauri CLI, and build tools
Open Repository

Compiled Release Workflow

  1. Open GitHub Releases.
  2. Choose the newest stable release.
  3. Download the package matching your operating system.
  4. Extract or mount the package, then move AdSlicer into your normal Applications or Programs location.
  5. Launch AdSlicer and choose an input video plus an output directory.
β„Ή
Compiled releases are the simplest installation path. Building from source is not required to process video or use the normal application workflow.

Build-from-Source Summary

git clone https://github.com/schwwaaa/AdSlicer.git
cd AdSlicer
chmod +x build.sh
./build.sh setup-bins
./build.sh mac-universal   # macOS universal application
# or
./build.sh windows         # Windows x86_64

See Building from Source for prerequisites, development mode, sidecar setup, and target-specific commands.

Quick Start

1. Choose your input

Select a single video file, or switch to Batch Folder mode and select a directory. All matching video files inside will be queued.

2. Set your output folder

A subfolder is created per input file β€” you'll never lose track of which output came from which tape. Results are never overwritten; re-processing appends _1, _2, etc.

3. Pick a preset

Open the Presets menu and choose the one closest to your source material. See Preset System for descriptions.

4. Dry run first

Enable Dry Run before committing to a full export. This runs the full detection pipeline and writes all logs, but cuts no media. Review detect.json and check dataset.jsonl for cuts where only sig_black_boundary fired and confidence is below 0.90 β€” those are the weakest detections and worth inspecting first.

5. Final export

Disable Dry Run. Enable Re-encode for frame-accurate archival cuts (H.264/AAC). Run.

Recommended workflow:

  1. Enable Dry Run
  2. Review activity log and detect.json
  3. Adjust parameters if needed, re-run dry
  4. Disable Dry Run, enable Re-encode
  5. Run final export
πŸ’‘
We default to -c copy for speed. Stream copy snaps to the nearest keyframe β€” a few frames of error at each boundary. Enable reencode for surgical precision.

Output Structure

<outdir>/ <basename>/ commercials/ <basename>_ad_0001.mp4 <basename>_ad_0002.mp4 ... show/ _parts/ part_0001.mp4 part_0002.mp4 <basename>_show.mp4 logs/ detect.json ← full structured plan detect.csv ← flat interval table detect.edl ← EDL (Kodi, MPC-HC, mkvmerge) chapters.ffmeta ← ffmpeg chapter metadata run_manifest.json ← all parameters + detection counts dataset.jsonl ← ML feature vectors (74 columns) ffmpeg_blackdetect.log ← verbosity β‰₯ 1 ffmpeg_silencedetect.log ← verbosity β‰₯ 1 ffmpeg_uniformdetect.log ← verbosity β‰₯ 2 ffmpeg_scenechange.log ← verbosity β‰₯ 2

Embedding chapter markers

Keep segments become Content N chapters; commercial blocks become Advertisement N. Embed into the show file:

ffmpeg -i show.mp4 -i logs/chapters.ffmeta \
  -map_metadata 1 -c copy show_with_chapters.mp4

Recognized by VLC, mpv, Kodi, and any player that reads ffmpeg metadata.

How It Works

Each commercial candidate passes through four independent detection passes in sequence. Every signal that fires is recorded against the interval and reflected in its confidence score.

Detection Passes

1
Black Frame Detection
Uses ffmpeg blackdetect to locate near-black frames. Segments shorter than blackMinDur are discarded. Segments within mergeGap seconds are merged.
2
Audio Silence Corroboration (Comskip: validate_silence)
Uses ffmpeg silencedetect. Candidates overlapping a silence segment by β‰₯ 0.5 s receive silence_overlap and a +0.05 confidence boost. Set silenceNoiseDb β‰₯ 0 to disable.
3
Uniform Frame Corroboration (Comskip: validate_uniform)
Uses ffmpeg showinfo to compute per-frame luma stddev. Frames with stddev ≀ uniformMaxStddev are classified as uniform slates. Candidates overlapping β‰₯ 0.3 s receive uniform_overlap and +0.04 boost. Set uniformMaxStddev to 0 to disable.
4
Scene Change Rate Scoring (Comskip: validate_scenechange)
Uses ffmpeg select=scene. Blocks exceeding 1.3Γ— the file average scene rate receive high_scene_rate and +0.04 boost. Set sceneThreshold to 0 to disable.

Scoring Guards

GuardParameterComskip equivalent
Uncorroborated penaltyautomaticpunish_modifier
Minimum show segmentminShowSegmentmin_show_segment_length
Edge protectionalwaysKeepFirst / alwaysKeepLastalways_keep_first/last_seconds
30s boundary snappingrequireDiv5require_div5
Asymmetric trimremoveBefore / removeAfterremove_before / remove_after

Confidence Score

Every CutInterval carries a confidence float (0.0–1.0) and a signals list. The activity log renders confidence as a star rating:

ScoreDisplayMeaning
β‰₯ 1.0β˜…β˜…β˜…Multiple corroborating signals
β‰₯ 0.8β˜…β˜…β˜†At least one corroborating signal
< 0.8β˜…β˜†β˜†Black boundary only β€” no corroboration

All Parameters

Input / Output

ParameterTypeDescription
inputModesingleFile | batchDirProcess one file or a whole folder
inputPathpathInput file or folder path
globpatternComma-separated globs for batch mode (e.g. *.mp4,*.mov,*.dv)
outdirpathBase output directory β€” a subfolder is created per input file

Black Frame Detection

ParameterDefaultDescription
blackMinDur0.10 sMinimum black segment duration. Shorter flashes are discarded.
pixTh0.08Pixel luma threshold for blackdetect. Lower = stricter black definition.
picTh0.98Fraction of pixels per frame that must be below pixTh.
mergeGap1.5 sMerge black segments separated by ≀ this gap. Prevents flickering slugs from splitting boundaries.

Cut Behaviour

ParameterDefaultDescription
edgePadPre0.20 sPadding added before each cut boundary.
edgePadPost0.06 sPadding added after each cut boundary.
minCommercial5 sMinimum gap to classify as a commercial break.
maxCommercial240 sMaximum gap to classify as a commercial break.
includeBlackfalseInclude surrounding black frames inside exported commercial clips.
reencodefalseRe-encode output with H.264/AAC for frame-accurate cuts.
dryRunfalseWrite logs only β€” no media files are created.

Advanced Detection (Comskip-derived)

ParameterDefaultComskip equiv.Description
silenceNoiseDb-40 dBmax_silenceAudio noise floor. Set β‰₯ 0 to disable silence detection.
silenceMinDur0.5 smin_silenceMinimum silence duration to register as a segment.
minShowSegment30 smin_show_segment_lengthMinimum keep-segment length. Cuts that would leave shorter keeps are demoted.
alwaysKeepFirst0 salways_keep_first_secondsHard-protect first N seconds from being cut.
alwaysKeepLast0 salways_keep_last_secondsHard-protect last N seconds from being cut.
uniformMaxStddev8.0non_uniformityLuma stddev ceiling for uniform frame detection. Set to 0 to disable.
sceneThreshold0.4schange_thresholdScene change sensitivity. Set to 0 to disable.
removeBefore0 sremove_beforeTrim from the content side of each cut.
removeAfter0 sremove_afterTrim from the ad side of each cut.
requireDiv5falserequire_div5Snap or drop candidates not within 3 s of a 30-second multiple.

Verbosity

ValueOutput
0Errors only
1Milestones + raw blackdetect/silencedetect logs written to logs/
2Full step-by-step + all raw filter logs written to logs/

Preset System

AdSlicer ships with three built-in presets and a full save/load system.

Built-in Presets

FilePurpose
default.jsonBalanced starting point for typical VHS
vhs_noisy.jsonLoose thresholds for degraded/worn tape
broadcast_strict.jsonStrict thresholds with 30s snapping for clean off-air captures

Preset Menu

Presets
  ── BUILT-IN ──────────────
  Broadcast strict
  Default
  VHS noisy
  ── MY PRESETS ────────────
  my_custom_settings
  ──────────────────────────
  Save Current as Preset…
  ──────────────────────────
  Open User Presets Folder…
  Reload Presets

User Preset Locations

PlatformPath
macOS~/Library/Application Support/net.schwwaaa.adslice/presets/
Windows%APPDATA%\net.schwwaaa.adslice\presets\
Linux~/.config/net.schwwaaa.adslice/presets/

Use Presets β†’ Open User Presets Folder… to open this location. Drop any .json file there and use Reload Presets to make it appear in the menu.

Preset File Format

Plain JSON. _preset sets the menu label; _description sets the tooltip. Unrecognized keys are silently ignored.

{
  "_preset": "My custom VHS settings",
  "_description": "Tuned for my specific deck and capture card.",
  "blackMinDur": 0.10,
  "pixTh": 0.08,
  "picTh": 0.98,
  "mergeGap": 1.5,
  "minCommercial": 5,
  "maxCommercial": 240,
  "silenceNoiseDb": -40,
  "requireDiv5": false
}

Adding a Built-in Preset to the Build

Drop a .json file into src-tauri/presets/ and rebuild. The tauri.conf.json resources glob picks it up β€” no code changes needed.

Tips & Tricks

AdSlicer works best as a review-assisted archival tool: analyze first, inspect the uncertain boundaries, then render only after the plan looks correct. These practices reduce accidental content loss and make large tape collections much faster to process.

Dry Run Before Every New Source Type

Run detection without exporting media when you change tape decks, capture hardware, channels, decades, or recording quality. One short dry run is cheaper than re-rendering a multi-hour tape.

Review Weak Boundaries First

Start with short intervals, low-confidence candidates, and cuts supported only by sig_black_boundary. These are the areas most likely to need manual inspection or parameter adjustment.

Tune One Representative Tape

Before processing a folder, choose one recording that represents the batch. Tune that file, save the settings as a preset, and then apply the preset to the remaining captures.

Keep the Original Capture Untouched

Export into a separate project folder. Preserve the full source recording as the archival master, then treat the clean show and isolated commercials as derived access files.

Fast, Safe Review Workflow

  1. Import the full recording.
  2. Run detection with Dry Run enabled.
  3. Inspect suspect short intervals and low-confidence boundaries first.
  4. Adjust only the settings needed for the source.
  5. Repeat the dry run until the detection plan is trustworthy.
  6. Enable Re-encode for the final frame-accurate archival export.
  7. Sort the rendered outputs into shows, commercials, promos, station IDs, and other archival categories.

Choose Speed or Precision Intentionally

GoalRecommended ModeWhy
Test a detection planDry RunWrites the plan and diagnostics without spending time rendering media.
Make a quick review copyStream copyVery fast, but boundaries may snap to nearby keyframes.
Create the final archive outputRe-encodeProvides frame-accurate cuts and consistent H.264/AAC output.
Process many related tapesSaved preset + batch modeReuses a tested configuration across a consistent collection.

Source-Specific Tricks

Noisy or Near-Black VHS Transitions

  • Raise pixTh slightly and lower picTh so analog black does not have to be perfectly clean.
  • Increase mergeGap when a black separator flickers or contains brief tracking noise.
  • Keep requireDiv5 disabled when tape timing has drifted away from exact broadcast durations.

Protect Openings and End Credits

  • Use alwaysKeepFirst to protect cold opens, station intros, and leading material.
  • Use alwaysKeepLast to protect credits, post-credit tags, and tape-end material.
  • Increase minShowSegment when short dark scenes are being mistaken for breaks.

Organize the Output Immediately

  • Keep the generated logs/ folder with every processed tape; it is the audit trail for how the result was produced.
  • Rename or catalog commercials only after the automatic segmentation is complete.
  • Use chapters.ffmeta, EDL, CSV, or JSON output when another archival or editorial tool needs the boundary data.
β˜…
The goal is not to inspect every frame. Let AdSlicer narrow the recording to a small number of suspect boundaries, then spend human attention only where it matters.

Tuning Guide

Thresholds may require tuning for darker or noisier analog captures. Always Dry Run first and review dataset.jsonl before committing to export.

Too many false positives (content being cut)

  • Raise blackMinDur (0.15–0.25) β€” require longer slugs
  • Raise picTh (0.99) β€” require nearly pure black frames
  • Increase minShowSegment (60–120 s) β€” prevent short content being consumed
  • Enable requireDiv5 for clean broadcast β€” non-multiples of 30 s are not real ad breaks
  • Raise minCommercial β€” filter breaks too short to be real commercials
  • Check dataset.jsonl for cuts where only sig_black_boundary fired β€” weakest detections

Missed commercials (breaks not detected)

  • Lower blackMinDur (0.06–0.08) β€” accept shorter slugs
  • Raise pixTh (0.10–0.14) β€” more permissive black definition
  • Lower picTh (0.90–0.95) β€” allow noisier black frames
  • Increase mergeGap for flickering VHS slug patterns
  • Lower sceneThreshold (0.25–0.35) β€” catch more cuts within blocks

Noisy or degraded VHS

  • Raise pixTh + lower picTh β€” the standard analog adjustment
  • Raise uniformMaxStddev (12–18) β€” VHS black slugs are never truly uniform
  • Set removeBefore 0.1 β€” recovers content clipped by ambiguous slug entry points
  • Disable requireDiv5 β€” VHS timing is irregular
  • Lower silenceNoiseDb to -35 dB β€” VHS audio floor is noisier

Clean off-air broadcast

  • Enable requireDiv5 β€” US TV commercials are exact 15/30/60/90 s units
  • Set alwaysKeepFirst 15 and alwaysKeepLast 15 β€” protect cold opens and credits
  • Lower uniformMaxStddev to 5–6 β€” broadcast slates are near-perfect
  • Raise sceneThreshold to 0.45 β€” hard cuts only; avoid dissolve false positives

Recommended workflow

  1. Run with dryRun enabled β€” review detect.json and the activity log
  2. Check dataset.jsonl β€” confidence below 0.90 or only sig_black_boundary firing is worth inspecting
  3. Adjust parameters and re-run dry until the plan is correct
  4. Remove dryRun and enable reencode for final archival export

ML Dataset Output

Every run writes logs/dataset.jsonl β€” one JSON object per line, one line per segment, 74 columns. Load it directly:

import pandas as pd
df = pd.read_json("logs/dataset.jsonl", lines=True)

Column Groups

Identity (4 cols)

ColumnTypeDescription
run_idstringISO-8601 UTC timestamp of the processing run
source_filestringInput filename stem
segment_indexintIndex within this label type
timeline_positionintSequential position in the overall file timeline

Timing (9 cols)

ColumnDescription
start_s, end_s, dur_sAbsolute timestamps and duration in seconds
start_norm, end_norm, dur_normPosition and duration as fraction of file length (0–1)
offset_from_start_sSeconds from start of recording
offset_from_end_sSeconds from end of recording

Signal Indicators β€” all 0.0 or 1.0 (11 cols)

ColumnFires when
sig_black_boundaryInterval is bracketed by a black slug
sig_within_commercial_rangeDuration within [min_commercial, max_commercial]
sig_silence_overlapSilence corroboration fired
sig_uniform_overlapUniform frame corroboration fired
sig_high_scene_rateScene rate exceeds 1.3Γ— file average
sig_demoted_min_show_segmentWas a commercial candidate, demoted by show guard
sig_always_keep_first/lastInterval falls within the always-keep window
sig_content_between_commercialsStandard keep between two commercial blocks
sig_div5_snappedBoundary was snapped to a 30 s multiple

Classification (3 cols)

ColumnValues
label"commercial" or "keep"
label_int1 = commercial, 0 = keep
confidenceDetection confidence score 0.0–1.0

Usage Examples

import pandas as pd
from sklearn.ensemble import RandomForestClassifier

df = pd.read_json("logs/dataset.jsonl", lines=True)

# Feature matrix
X = df[[
    "dur_s", "dur_norm", "start_norm",
    "black_left_dur_s", "black_right_dur_s",
    "silence_coverage", "has_silence_overlap",
    "scene_change_rate", "scene_change_rate_vs_avg",
    "sig_black_boundary", "sig_silence_overlap",
]]
y = df["label_int"]

# Compare across parameter tuning runs
runs = pd.concat([
    pd.read_json("run1/logs/dataset.jsonl", lines=True),
    pd.read_json("run2/logs/dataset.jsonl", lines=True),
])
runs.groupby("param_scene_threshold")["run_commercial_ratio"].mean()

# Inspect low-confidence cuts
df[(df["label"] == "commercial") & (df["confidence"] < 0.9)]
β„Ή
All param_* columns are fully denormalised. Individual files can be concatenated across runs and remain independently queryable.

Use Cases

AdSlicer is designed for recordings where the commercials, program material, transitions, and broadcast artifacts are all historically usefulβ€”but need to be separated into practical, reviewable outputs.

Preserving a Complete Broadcast and a Clean Viewing Copy

A collector digitizes an off-air movie, sports broadcast, or television block from VHS. AdSlicer preserves the original capture, creates a clean show master, isolates commercial blocks, and writes detection metadata so both versions remain traceable to the same source.

Processing Large VHS and Broadcast Collections

An archive, library, preservation group, or individual collector has hundreds of related tapes. A representative tape is tuned first, its settings are saved as a preset, and batch mode then produces consistent folder structures and diagnostics across the collection.

Recovering Vintage Commercials, Promos, and Station IDs

Commercial blocks can be exported as separate clips for historical research, brand studies, broadcast design reference, compilation editing, or cataloging. The program is not merely deleting advertisementsβ€”it is separating two valuable classes of archival material.

Preparing Ad-Free Program Masters

Editors and collectors can create watchable copies of cartoons, movies, music programs, news, and episodic television while retaining the source capture and isolated advertisements elsewhere in the project.

Boundary Review and Quality Control

Detection logs identify short, weak, or unusual candidate intervals that deserve attention. Reviewers can focus on suspect boundaries instead of manually scrubbing through every hour of the recording.

Building Research and Machine-Learning Datasets

The structured dataset.jsonl, detect.json, CSV, EDL, and run manifest outputs provide labeled timing, confidence, signal, and parameter data for commercial-detection research, comparative testing, and future model development.

Creating Editorial Compilations

Once commercial blocks are extracted, an editor can sort clips by brand, year, network, product category, visual style, or campaign. The same workflow also supports promo reels, station-identification collections, and historical broadcast packages.

Integrating With Other Archive Tools

EDL, chapter metadata, CSV, and JSON outputs can be handed to media players, command-line processes, database ingest tools, or nonlinear editors without forcing every downstream system to repeat the detection pass.

πŸ’‘
AdSlicer’s most important archival advantage is that it keeps both sides of the broadcast useful: program material becomes easier to watch, while commercials and interstitials remain available for research and preservation.

Building from Source

This path is intended for developers, contributors, and users who need a custom application build. Users who only want to run AdSlicer should use the compiled package described under Installation.

Prerequisites

  • Git
  • Rust and Cargo
  • Tauri CLI
  • Platform build tools for macOS or Windows
  • curl or wget, plus unzip

Clone the repository

git clone https://github.com/schwwaaa/AdSlicer.git
cd AdSlicer
chmod +x build.sh

First-time sidecar setup

Download the static FFmpeg and FFprobe binaries that Tauri bundles with the application. The target-specific filenames are required before compilation.

./build.sh setup-bins

Dev mode

cd src-tauri
cargo tauri dev

Release builds

CommandTarget
./build.shAuto-detect current OS
./build.sh mac-universalmacOS arm64 + x86_64 fat binary
./build.sh mac-armmacOS Apple Silicon only
./build.sh mac-x86macOS Intel only
./build.sh windowsWindows x86_64

ffmpeg and ffprobe are bundled automatically. Users need no external dependencies.

Adding a built-in preset

Drop a .json file into src-tauri/presets/ and run ./build.sh. The tauri.conf.json resources glob picks it up β€” no code changes needed.

Introduction
AdSlicer Help v2.0