Skip to content

Latest commit

 

History

History
304 lines (224 loc) · 10.5 KB

File metadata and controls

304 lines (224 loc) · 10.5 KB

Podcast Ad-Blocking POC - Status Report

✅ COMPLETED - POC is Ready to Test!

Date: December 26, 2025 Server Status: Running on http://localhost:3000 Compilation: ✅ Successfully compiled 1510 modules


🎯 What's Been Implemented

1. Core Ad Segment Services

Episode Identity System (adSegmentIdentity.ts)

  • GUID-based episode keys (primary)
  • SHA-256 hash fallback: hash(feedUrl + enclosureUrl + pubDate)
  • CDATA normalization - handles <![CDATA[ guid ]]> wrappers in RSS feeds
  • Helper functions for Podverse NowPlayingItem objects

Ad Segment Validation & Merging (adSegmentMerge.ts)

  • Validates ad segments (startTime < endTime, non-negative)
  • O(n log n) interval merging for overlapping ads
  • O(log n) binary search for finding ad at current time
  • Statistics: overlap detection, merged count

Fixture Provider (adSegmentFixtureProvider.ts)

  • Implements AdSegmentProvider interface
  • Loads from src/lib/fixtures/adSegments/{episodeKey}.json
  • In-memory caching
  • Tagger profile loading from src/lib/fixtures/profiles/taggers.json

Auto-Skip Logic (playerAdSkip.ts)

  • PlayerAdSkipManager singleton with skip guards:
    • 1000ms debounce window
    • Tracks last skipped segment
    • Allows re-entry after manual scrub backward
  • Public API: initializeAdSkipForEpisode(), setSkipAdsEnabled(), handlePlayerTimeUpdate()

2. Player Integration

Modified Files:

3. Test Data - Real Podcast Episodes

Three Real RSS Feeds with Actual MP3 Files:

Test Podcast Episode GUID MP3 File Ads
1 What Bitcoin Did ec8b4655-cb61-4d69-87ee-dbdba77c0a62 AUDIO---DEFAULT---dcfdc6d6-489e-4ac7-b9a4-5629cc632395.mp3 3 ads
2 TFTC 2d4217bb-799b-4192-a559-348e82e2ea0e AUDIO---DEFAULT---34eb3a45-d135-453e-a790-58a744da35ba.mp3 3 ads
3 TIP b47746b8-daa3-11f0-b08a-233a79f7667c PPLLC1896786790.mp3 3 ads (CDATA GUID)

Ad Timecodes (in seconds):

Test 1 - What Bitcoin Did:

  • Pre-roll: 2s → 60s (00:00:02 - 00:01:00)
  • Mid-roll #1: 669s → 815s (00:11:09 - 00:13:35)
  • Mid-roll #2: 2263s → 2403s (00:37:43 - 00:40:03)

Test 2 - TFTC:

  • Pre-roll: 3s → 31s (00:00:03 - 00:00:31)
  • Mid-roll #1: 1632s → 1759s (00:27:12 - 00:29:19)
  • Mid-roll #2: 2569s → 2689s (00:42:49 - 00:44:49)

Test 3 - TIP:

  • Pre-roll: 50s → 88s (00:00:50 - 00:01:28)
  • Mid-roll #1: 963s → 1196s (00:16:03 - 00:19:56)
  • Mid-roll #2: 1922s → 2133s (00:32:02 - 00:35:33)

4. Unit Tests

Comprehensive Test Coverage:

Run tests:

npm test

5. Documentation

Complete Documentation:


🚀 How to Test the POC

Quick Start (Browser Console Testing)

Since this is a POC without full database integration, the fastest way to test is via browser console:

  1. Open the app: http://localhost:3000
  2. Open Browser DevTools (F12)
  3. Go to Console tab
  4. Run the test commands below

Test Episode 1 (What Bitcoin Did)

// Import the necessary functions
const { extractEpisodeKeyFromNowPlayingItem } = await import('/src/services/adSegments/adSegmentIdentity.ts')
const { fixtureAdSegmentProvider } = await import('/src/services/adSegments/adSegmentFixtureProvider.ts')
const { mergeAdSegments } = await import('/src/services/adSegments/adSegmentMerge.ts')

// Test episode 1
const testEpisode1 = {
  episodeGuid: 'ec8b4655-cb61-4d69-87ee-dbdba77c0a62',
  podcastFeedUrl: 'https://feeds.fountain.fm/UZSKQcrOnhqYS1JopxGg',
  episodeMediaUrl: 'https://feeds.fountain.fm/UZSKQcrOnhqYS1JopxGg/items/RpJavE7EEgZNW5hpgUDJ/files/AUDIO---DEFAULT---dcfdc6d6-489e-4ac7-b9a4-5629cc632395.mp3'
}

const episodeKey = extractEpisodeKeyFromNowPlayingItem(testEpisode1)
console.log('Episode Key:', episodeKey)

const adSegments = await fixtureAdSegmentProvider.fetchAdSegments(episodeKey)
console.log('Ad Segments:', adSegments)

const mergedSegments = mergeAdSegments(adSegments)
console.log('Merged Ad Segments:', mergedSegments)

Expected Output:

Episode Key: ec8b4655-cb61-4d69-87ee-dbdba77c0a62
Ad Segments: (3) [{…}, {…}, {…}]
  0: {id: 'ad-test1-001', startTime: 2, endTime: 60, …}
  1: {id: 'ad-test1-002', startTime: 669, endTime: 815, …}
  2: {id: 'ad-test1-003', startTime: 2263, endTime: 2403, …}
Merged Ad Segments: (3) [{…}, {…}, {…}]

Test Episode 3 (CDATA GUID - TIP)

const testEpisode3 = {
  episodeGuid: '<![CDATA[ b47746b8-daa3-11f0-b08a-233a79f7667c ]]>',
  podcastFeedUrl: 'https://feeds.megaphone.fm/PPLLC8974708240',
  episodeMediaUrl: 'https://www.podtrac.com/pts/redirect.mp3/pdst.fm/e/traffic.megaphone.fm/PPLLC1896786790.mp3'
}

const episodeKey3 = extractEpisodeKeyFromNowPlayingItem(testEpisode3)
console.log('Episode Key (CDATA normalized):', episodeKey3)
// Should output: b47746b8-daa3-11f0-b08a-233a79f7667c (without CDATA wrapper)

const adSegments3 = await fixtureAdSegmentProvider.fetchAdSegments(episodeKey3)
console.log('Ad Segments:', adSegments3)

Expected Output:

Episode Key (CDATA normalized): b47746b8-daa3-11f0-b08a-233a79f7667c
Ad Segments: (3) [{…}, {…}, {…}]
  0: {id: 'ad-test3-001', startTime: 50, endTime: 88, …}
  1: {id: 'ad-test3-002', startTime: 963, endTime: 1196, …}
  2: {id: 'ad-test3-003', startTime: 1922, endTime: 2133, …}

Verify MP3 Files Are Accessible

Open these URLs in your browser to confirm the MP3 files are publicly accessible:


📋 Testing Checklist

Use TESTING_GUIDE.md for the complete testing procedure. Here's a quick checklist:

Core Functionality

  • Ad segments load from fixtures (check console log)
  • Skip Ads toggle appears in player controls
  • Toggle ON/OFF works (visual state change)
  • Auto-skip jumps to ad endTime when toggle is ON
  • No skip occurs when toggle is OFF

GUID Handling

  • Test 1 & 2: Plain GUID works
  • Test 3: CDATA-wrapped GUID works (normalized correctly)
  • Console shows correct episode key for all three

Skip Guards

  • Each ad segment only skipped once per entry
  • Re-scrubbing into ad triggers skip again
  • No infinite skip loops (debounce works)
  • Console logs show skip actions clearly

🐛 Troubleshooting

Problem: Ad segments not loading

Check:

  1. Console for error messages
  2. Fixture filenames match episode GUIDs exactly
  3. JSON files are valid (no syntax errors)

Debug:

// In browser console:
const { generateEpisodeKey } = await import('/src/services/adSegments/adSegmentIdentity.ts')

const testGuid = 'ec8b4655-cb61-4d69-87ee-dbdba77c0a62'
const key = generateEpisodeKey({ guid: testGuid })
console.log('Generated key:', key)
// Should match fixture filename

Problem: Skip not working

Check:

  1. Skip Ads toggle is ON (check button state)
  2. Console shows skip logs when entering ad
  3. Ad timecodes are correct (check fixture JSON)
  4. Player is using audio (not video)

Debug:

// In browser console:
const { getSkipAdsEnabled, getMergedAdSegments } = await import('/src/services/player/playerAdSkip.ts')

console.log('Skip Ads Enabled:', getSkipAdsEnabled())
console.log('Merged Segments:', getMergedAdSegments())

Problem: CDATA GUID not working (Test 3)

Check:

const { generateEpisodeKey } = await import('/src/services/adSegments/adSegmentIdentity.ts')

const cdataGuid = '<![CDATA[ b47746b8-daa3-11f0-b08a-233a79f7667c ]]>'
const key = generateEpisodeKey({ guid: cdataGuid })
console.log('Normalized key:', key)
// Should be: b47746b8-daa3-11f0-b08a-233a79f7667c (without CDATA)

🎯 Success Criteria

The POC is successful if:

✅ All three episodes load ad segments correctly (console log confirms) ✅ GUID normalization works for all formats (plain + CDATA) ✅ Skip Ads toggle appears and works ✅ Auto-skip jumps to ad endTime when enabled ✅ Skip guards prevent infinite loops ✅ Re-entering ads triggers skip again ✅ Toggle OFF disables auto-skip ✅ No player crashes or critical errors


📚 Next Steps

  1. Run browser console tests to verify fixture loading and GUID normalization
  2. Test auto-skip functionality (if player integration is working)
  3. Run unit tests: npm test
  4. Review documentation for future Nostr integration plan

🔧 Technical Notes

Dependency Resolution

Issue: @sentry/nextjs 8.52.1 required Next.js 13.2.0+ but project uses 12.3.4 Fix: Downgraded to @sentry/nextjs@7.119.0 (compatible with Next.js 12)

Windows Compatibility

Issue: npm run dev uses Unix-style NODE_OPTIONS='--inspect' syntax Workaround: Run npx next dev directly instead of npm script

Current Server Status

✅ Running on http://localhost:3000 ✅ Compiled successfully (1510 modules) ⚠️ Warnings (non-critical):

  • Sentry config property not in Next.js 12 schema (expected for older version)
  • Browserslist outdated (cosmetic)

POC Status: READY FOR TESTING 🎉

For detailed testing procedures, see TESTING_GUIDE.md