feat: chapter detection from silence structure (FFMETADATA/JSON export)#187
Open
seonghobae wants to merge 1 commit into
Open
feat: chapter detection from silence structure (FFMETADATA/JSON export)#187seonghobae wants to merge 1 commit into
seonghobae wants to merge 1 commit into
Conversation
Add chapters.py, a stdlib-only module that turns detected silence intervals plus total duration into proposed chapter markers for long recordings (lectures, meetings). Silences of at least min_gap_seconds end a chapter at their midpoint; chapters shorter than min_chapter_seconds merge into the previous chapter; output always covers [0, total_duration]. The module is independent of media_shrinker: it accepts any object with start_seconds/end_seconds attributes (same duck-type shape as SilenceInterval), so it pairs with the existing silencedetect machinery without a hard import. Exports: - to_ffmetadata(): ffmpeg ;FFMETADATA1 chapters (TIMEBASE=1/1000, START/END in ms) for embedding player chapter navigation - to_json(): simple JSON listing Edge cases covered: zero/negative duration raises ValueError, out-of-range silences clamped, unsorted/overlapping silences sorted and merged, empty silences yield a single chapter. Tests: tests/test_chapters.py (15 cases). Interrogate 100%. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CJRVbDrp1vGYkJgNHMGPpG
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
New module
chapters.py: proposes chapter markers for long recordings (lectures, meetings) from the silence structure that the existing silencedetect machinery already produces. Players show chapter navigation when the FFMETADATA output is embedded via ffmpeg.detect_chapters(silences, total_duration, min_chapter_seconds=60.0, min_gap_seconds=3.0)— a silence lasting at leastmin_gap_secondsends a chapter at its midpoint; chapters shorter thanmin_chapter_secondsmerge into the previous chapter (first merges forward); output always covers[0, total_duration]; no silences → single chapter.to_ffmetadata(chapters)—;FFMETADATA1header +[CHAPTER]blocks withTIMEBASE=1/1000and START/END in integer milliseconds, ready forffmpeg -i input -i chapters.txt -map_metadata 1 -codec copy output.to_json(chapters)— simple JSON listing.Design
media_shrinker. Accepts any object withstart_seconds/end_seconds(duck-type contract matchingSilenceInterval), declared as aProtocol.ValueError; silences beyond the duration are clamped; unsorted/overlapping silences are sorted and merged first.Testing
python3.14 -m unittest discover -s tests: 128 tests, no new failures (baseline exactly 5 macOSos.listxattrmock errors).python3.14 -m interrogate -c pyproject.toml chapters.py: 100% docstring coverage.tests/test_chapters.py(15 cases): midpoint boundaries, short-chapter merging (trailing and leading), single chapter with no silences, exact FFMETADATA format, clamping, unsorted/overlapping input, invalid duration.🤖 Generated with Claude Code