Skip to content

Latest commit

 

History

History
293 lines (228 loc) · 9.63 KB

File metadata and controls

293 lines (228 loc) · 9.63 KB

Real RSS Feeds Setup Guide

This document explains the setup for the three real podcast RSS feeds used in the POC.

✅ Completed Setup

1. GUID Normalization (CDATA Support)

The code now handles all three GUID formats correctly:

Test 1 & 2: Plain UUID

<guid isPermaLink="false">ec8b4655-cb61-4d69-87ee-dbdba77c0a62</guid>

Test 3: CDATA-wrapped UUID

<guid isPermaLink="false"><![CDATA[ b47746b8-daa3-11f0-b08a-233a79f7667c ]]></guid>

The normalizeGuid() function in adSegmentIdentity.ts automatically:

  • Strips CDATA wrappers using regex: /^<!\[CDATA\[([\s\S]*?)\]\]>$/
  • Trims whitespace
  • Returns normalized GUID or falls back to hash if empty/missing

2. Fixture Files Created

Three fixture JSON files matching the episode GUIDs:

Episode GUID Fixture File
What Bitcoin Did (Test 1) ec8b4655-cb61-4d69-87ee-dbdba77c0a62 ec8b4655-cb61-4d69-87ee-dbdba77c0a62.json
TFTC (Test 2) 2d4217bb-799b-4192-a559-348e82e2ea0e 2d4217bb-799b-4192-a559-348e82e2ea0e.json
TIP (Test 3) b47746b8-daa3-11f0-b08a-233a79f7667c b47746b8-daa3-11f0-b08a-233a79f7667c.json

3. MP3 Files Location

You've already placed the MP3 files in public/test-podcasts/:

public/test-podcasts/
├── AUDIO---DEFAULT---dcfdc6d6-489e-4ac7-b9a4-5629cc632395.mp3  (Test 1)
├── AUDIO---DEFAULT---34eb3a45-d135-453e-a790-58a744da35ba.mp3  (Test 2)
├── PPLLC1896786790.mp3  (Test 3)
├── MAPPING.md
└── README.md

These are accessible at:

  • http://localhost:3000/test-podcasts/AUDIO---DEFAULT---dcfdc6d6-489e-4ac7-b9a4-5629cc632395.mp3
  • http://localhost:3000/test-podcasts/AUDIO---DEFAULT---34eb3a45-d135-453e-a790-58a744da35ba.mp3
  • http://localhost:3000/test-podcasts/PPLLC1896786790.mp3

4. Unit Tests Added

Added comprehensive tests for GUID normalization in adSegmentIdentity.test.ts:

test('strips CDATA wrapper from GUID', () => {
  const input = {
    guid: '<![CDATA[ b47746b8-daa3-11f0-b08a-233a79f7667c ]]>',
    // ...
  }
  const key = generateEpisodeKey(input)
  expect(key).toBe('b47746b8-daa3-11f0-b08a-233a79f7667c')
})

test('handles real-world test episode GUIDs', () => {
  // Tests all 3 actual episodes
})

📋 Episode Details

Test 1: What Bitcoin Did

  • Feed: https://feeds.fountain.fm/UZSKQcrOnhqYS1JopxGg
  • Episode: "Fiat Money, Inflation & the Collapse of Civilization | Saifedean Ammous"
  • Duration: 4020 seconds (67 minutes)
  • GUID: ec8b4655-cb61-4d69-87ee-dbdba77c0a62 (plain)
  • Chapters: YES - <podcast:chapters> element present
  • AlternateEnclosures: NO
  • MP3: AUDIO---DEFAULT---dcfdc6d6-489e-4ac7-b9a4-5629cc632395.mp3

Test 2: TFTC (Tales From The Crypt)

  • Feed: https://feeds.fountain.fm/ZwwaDULvAj0yZvJ5kdB9/
  • Episode: "#697: The Legal Fight Against UK Online Censorship with Preston Byrne"
  • Duration: 5239 seconds (87 minutes)
  • GUID: 2d4217bb-799b-4192-a559-348e82e2ea0e (plain)
  • Chapters: YES - <podcast:chapters> element present
  • AlternateEnclosures: YES - video + ad-free versions (ignored per POC requirements)
  • MP3: AUDIO---DEFAULT---34eb3a45-d135-453e-a790-58a744da35ba.mp3

Note: This episode has multiple <podcast:chapters> elements:

  1. Primary audio chapters (DEFAULT)
  2. Ad-free audio chapters (in alternateEnclosure)
  3. Video chapters (in alternateEnclosures)

Per POC requirements, we only use the primary chapters (not inside alternateEnclosure).

Test 3: The Investor's Podcast (TIP)

  • Feed: https://feeds.megaphone.fm/PPLLC8974708240
  • Episode: "TECH009: Data Centers in Space, AI Education, Haptic Touch Robotics..."
  • Duration: 4135 seconds (68 minutes)
  • GUID: b47746b8-daa3-11f0-b08a-233a79f7667c (CDATA wrapped)
  • Chapters: NO - no <podcast:chapters> element
  • AlternateEnclosures: NO
  • MP3: PPLLC1896786790.mp3

🎯 Next Steps: Edit Ad Timecodes

Step 1: Listen to Each Episode

Open each MP3 file and note the start/end times of any ad segments you find.

Use an audio player that shows timestamps (VLC, Audacity, or any podcast app).

Step 2: Edit the Fixture Files

For each ad you identify, update the startTime and endTime in the corresponding JSON file.

Example for Test 1:

If you find these ads in the What Bitcoin Did episode:

  • Pre-roll: 0:00 - 0:30
  • Mid-roll #1: 12:45 - 13:30
  • Mid-roll #2: 35:20 - 36:05
  • Post-roll: 66:15 - 66:45

Edit src/lib/fixtures/adSegments/ec8b4655-cb61-4d69-87ee-dbdba77c0a62.json:

{
  "episodeKey": "ec8b4655-cb61-4d69-87ee-dbdba77c0a62",
  "adSegments": [
    {
      "id": "ad-test1-001",
      "startTime": 0,      // 0:00 in seconds
      "endTime": 30,       // 0:30 in seconds
      "description": "Pre-roll ad - What Bitcoin Did episode",
      "taggerPubkey": "npub1tester1abc123"
    },
    {
      "id": "ad-test1-002",
      "startTime": 765,    // 12:45 in seconds (12*60 + 45)
      "endTime": 810,      // 13:30 in seconds (13*60 + 30)
      "description": "Mid-roll sponsor read #1",
      "taggerPubkey": "npub1tester2def456"
    },
    {
      "id": "ad-test1-003",
      "startTime": 2120,   // 35:20 in seconds (35*60 + 20)
      "endTime": 2165,     // 36:05 in seconds (36*60 + 5)
      "description": "Mid-roll sponsor read #2",
      "taggerPubkey": "npub1tester3ghi789"
    },
    {
      "id": "ad-test1-004",
      "startTime": 3975,   // 66:15 in seconds (66*60 + 15)
      "endTime": 4005,     // 66:45 in seconds (66*60 + 45)
      "description": "Post-roll ad",
      "taggerPubkey": "npub1tester1abc123"
    }
  ]
}

Time Conversion Formula:

seconds = (minutes × 60) + seconds

Examples:

  • 12:45 = (12 × 60) + 45 = 765 seconds
  • 35:20 = (35 × 60) + 20 = 2120 seconds

Step 3: Repeat for All Episodes

Edit all three fixture files:

  1. ec8b4655-cb61-4d69-87ee-dbdba77c0a62.json (Test 1)
  2. 2d4217bb-799b-4192-a559-348e82e2ea0e.json (Test 2)
  3. b47746b8-daa3-11f0-b08a-233a79f7667c.json (Test 3)

🧪 Verification

1. Check Episode Key Generation

Create a test script or check console logs:

import { generateEpisodeKey } from '~/services/adSegments/adSegmentIdentity'

// Test 1
const key1 = generateEpisodeKey({
  guid: 'ec8b4655-cb61-4d69-87ee-dbdba77c0a62',
  feedUrl: 'https://feeds.fountain.fm/UZSKQcrOnhqYS1JopxGg',
  enclosureUrl: 'https://feeds.fountain.fm/.../AUDIO---DEFAULT---dcfdc6d6-489e-4ac7-b9a4-5629cc632395.mp3'
})
console.log(key1) // Should output: ec8b4655-cb61-4d69-87ee-dbdba77c0a62

// Test 3 (CDATA)
const key3 = generateEpisodeKey({
  guid: '<![CDATA[ b47746b8-daa3-11f0-b08a-233a79f7667c ]]>',
  feedUrl: 'https://feeds.megaphone.fm/PPLLC8974708240',
  enclosureUrl: 'https://www.podtrac.com/pts/redirect.mp3/pdst.fm/e/traffic.megaphone.fm/PPLLC1896786790.mp3'
})
console.log(key3) // Should output: b47746b8-daa3-11f0-b08a-233a79f7667c

2. Run Unit Tests

npm test

Should pass all tests including the new CDATA normalization tests.

3. Test in Browser

  1. Start dev server: npm run dev
  2. Load one of the test episodes in Podverse
  3. Open browser console
  4. Look for log message:
    [AdSegments] Loaded X ad segments (merged to Y) for episode: <guid>
    
  5. Verify the GUID matches the expected value

🔍 Troubleshooting

Problem: Ad segments not loading

Check:

  1. Fixture filename matches episode GUID exactly
  2. JSON file is valid (use a JSON validator)
  3. File path uses forward slashes / not backslashes \
  4. Episode GUID is being normalized correctly (check console logs)

Debug:

// In browser console:
import { generateEpisodeKey } from '~/services/adSegments/adSegmentIdentity'

const nowPlayingItem = OmniAural.state.player.currentNowPlayingItem.value()
const key = generateEpisodeKey({
  guid: nowPlayingItem.episodeGuid,
  feedUrl: nowPlayingItem.podcastFeedUrl,
  enclosureUrl: nowPlayingItem.episodeMediaUrl
})
console.log('Generated episode key:', key)

Problem: CDATA not being stripped

Check:

  1. The regex pattern in normalizeGuid() is correct
  2. GUID string is exactly as it appears in RSS feed
  3. No extra characters or encoding issues

Test:

const testGuid = '<![CDATA[ b47746b8-daa3-11f0-b08a-233a79f7667c ]]>'
const normalized = normalizeGuid(testGuid)
console.log(normalized) // Should be: b47746b8-daa3-11f0-b08a-233a79f7667c

Problem: Wrong fixture file being loaded

Check:

  1. Episode is loading from the correct feed URL
  2. GUID in episode data matches fixture filename
  3. No typos in GUID (easy to mix up similar characters)

📚 Additional Resources

✅ Checklist

  • GUID normalization implemented (handles CDATA)
  • Three fixture files created with correct episode GUIDs
  • Unit tests added for CDATA stripping
  • MP3 files placed in public/test-podcasts/
  • Mapping documentation created
  • TODO: Edit ad timecodes in fixture files (after listening to MP3s)
  • TODO: Test loading episodes in browser
  • TODO: Verify auto-skip behavior

Once you've edited the ad timecodes, the POC will be ready to test! 🎉