How SmartTube Caches SponsorBlock Segments: A Deep Dive into the Source Code
SmartTube caches SponsorBlock segments in memory for the duration of a playback session using RxJava observables, while persisting user preferences to SharedPreferences via the SponsorBlockData class.
The open-source SmartTube project (yuliskov/SmartTube) implements a sophisticated two-tier caching strategy for SponsorBlock functionality. This approach separates transient video segment data from durable user settings, ensuring optimal performance without unnecessary disk I/O. Understanding how SmartTube cache SponsorBlock segments reveals an elegant architecture that balances network efficiency with persistent configuration management.
Understanding SmartTube's Two-Tier Caching Strategy
SmartTube distinguishes between configuration data and fetched segment data, handling each with different persistence mechanisms.
Persistent User Preferences (SponsorBlockData)
User-specific settings—including enabled categories, excluded channels, color markers, and "don't skip again" flags—are persisted to disk using Android's SharedPreferences. The SponsorBlockData class manages this storage layer.
In-Memory Segment Caching (SponsorBlockController)
Actual sponsor skip ranges for individual videos are cached only in memory for the lifetime of the playback session. The SponsorBlockController coordinates this through reactive observables that memoize network responses without writing to persistent storage.
How SponsorBlockData Persists Configuration
The SponsorBlockData class located at [SponsorBlockData.java](https://github.com/yuliskov/SmartTube/blob/master/common/src/main/java/com/liskovsoft/smartyoutubetv2/common/prefs/SponsorBlockData.java) handles all durable SponsorBlock preferences. It uses a pipe-delimited string format stored under the content_block_data key in SharedPreferences.
Persisting State to Disk
When settings change, persistState() serializes the configuration into a compact pipe-separated format:
private void persistState() {
String colorCategories = Helpers.mergeArray(mColorCategories.toArray());
String actions = Helpers.mergeArray(mActions.toArray());
String excludedChannels = Helpers.mergeArray(mExcludedChannels.toArray());
// Pipe‑delimited format: enabled|…|actions|colors|…|channels|…
mAppPrefs.setData(SPONSOR_BLOCK_DATA,
Helpers.mergeData(
mIsSponsorBlockEnabled, null, null, null,
null, null, actions, colorCategories,
mIsDontSkipSegmentAgainEnabled,
excludedChannels, mIsPaidContentNotificationEnabled,
mIgnoredDurationMs));
}
Restoring State on Launch
During application startup, restoreState() deserializes this data:
private void restoreState() {
String data = mAppPrefs.getData(SPONSOR_BLOCK_DATA);
String[] split = Helpers.splitData(data);
mIsSponsorBlockEnabled = Helpers.parseBoolean(split, 0, VERSION.SDK_INT > 19);
// …read colour categories, actions, excluded channels, etc.
}
This approach minimizes SharedPreferences overhead by consolidating multiple boolean and array values into a single key-value pair.
How Video Segments Are Cached During Playback
Unlike user preferences, fetched SponsorBlock segments are never written to disk. Instead, SmartTube leverages RxJava's observable memoization to cache network responses in RAM.
The Observable Caching Pattern
In [SponsorBlockController.java](https://github.com/yuliskov/SmartTube/blob/master/common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/playback/controllers/SponsorBlockController.java), line 179 initiates the fetch:
mCachedSegmentsAction = mMediaItemService.getSponsorSegmentsObserve(
item.videoId, getSponsorBlockData().getEnabledCategories());
The getSponsorSegmentsObserve() method returns an Observable<List<SponsorSegment>> that internally memoizes the result. Subsequent subscriptions for the same video ID receive the cached list immediately, eliminating redundant network requests during the playback session.
Session-Only Storage Characteristics
- Lifetime: Segments persist only while the player activity remains active
- Scope: Cache is keyed by video ID and category filters
- Memory pressure: Automatically cleared when the controller is destroyed or the user navigates away
This design optimizes for the YouTube use case where users typically watch a video once; persistent disk caching would provide minimal benefit while consuming storage.
Practical Implementation Examples
Enable SponsorBlock and Configure Categories
SponsorBlockData sb = SponsorBlockData.instance(context);
sb.setSponsorBlockEnabled(true);
sb.setAction(SponsorSegment.CATEGORY_INTRO, SponsorBlockData.ACTION_SKIP_WITH_TOAST);
sb.setAction(SponsorSegment.CATEGORY_SPONSOR, SponsorBlockData.ACTION_SKIP);
Exclude Specific Channels
sb.excludeChannel("UC12345abcd"); // Channel ID persisted immediately
Fetch Segments with Automatic Caching
// Inside SponsorBlockController – network call executes once
Observable<List<SponsorSegment>> segmentsObs =
mMediaItemService.getSponsorSegmentsObserve(videoId,
sb.getEnabledCategories());
// Subsequent subscriptions reuse cached data
segmentsObs.subscribe(segments -> {
// Process cached sponsor ranges
});
Reset All SponsorBlock Data
SponsorBlockData sb = SponsorBlockData.instance(context);
sb.setSponsorBlockEnabled(false);
sb.stopExcludingChannel(null); // Clears all channel exclusions
sb.disableColorMarker(null); // Clears visual markers
Summary
- SmartTube cache SponsorBlock segments using a dual-layer approach: durable
SharedPreferencesfor settings and in-memory RxJava observables for video data. - The
SponsorBlockDataclass persists user configuration as pipe-delimited strings viapersistState()andrestoreState()in [SponsorBlockData.java](https://github.com/yuliskov/SmartTube/blob/master/common/src/main/java/com/liskovsoft/smartyoutubetv2/common/prefs/SponsorBlockData.java). - Video segments are fetched through
MediaItemService.getSponsorSegmentsObserve()and cached only for the active playback session in [SponsorBlockController.java](https://github.com/yuliskov/SmartTube/blob/master/common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/playback/controllers/SponsorBlockController.java). - Segment data lives exclusively in RAM and is not written to disk, optimizing for single-view video consumption patterns.
- All user preferences—including category actions, excluded channels, and color markers—survive app restarts through the
content_block_datapreference key.
Frequently Asked Questions
Where does SmartTube store downloaded SponsorBlock segments?
SmartTube does not store SponsorBlock segments to disk. According to the yuliskov/SmartTube source code, segments are cached only in memory for the duration of the playback session using an RxJava observable pattern. The SponsorBlockController holds a reference to mCachedSegmentsAction, which memoizes the network response but clears when the player closes.
How long do SponsorBlock segments remain cached in SmartTube?
Segments remain cached only while the video playback session is active. The observable returned by getSponsorSegmentsObserve() maintains the cache for the specific video ID, but this cache is destroyed when the user exits the player or loads a new video. Persistent storage is reserved exclusively for user preferences, not segment data.
What SponsorBlock data does SmartTube save permanently?
SmartTube persists user-level configuration via the SponsorBlockData class, including: enabled/disabled state, per-category skip actions (skip, show toast, show dialog), color marker preferences, excluded channel lists, and "don't skip again" flags. These settings are serialized as pipe-delimited strings and stored in SharedPreferences under the key content_block_data.
Can I clear the SponsorBlock cache without resetting my preferences?
Since segment data exists only in memory, simply closing the video player or restarting the app clears the segment cache automatically. To clear persistent preferences like excluded channels or category settings, you must call methods on SponsorBlockData such as stopExcludingChannel(null) and disableColorMarker(null), or toggle the main SponsorBlock enabled state.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →