From 8c077f966dd73a81deb86a0479d413e4ea00abd7 Mon Sep 17 00:00:00 2001 From: Ethan Shen <42264778+nczitzk@users.noreply.github.com> Date: Sun, 18 Feb 2024 00:24:50 +0800 Subject: [PATCH] feat(route): add Transcript Forest (#14482) * feat(route): add Transcript Forest * fix: add transcript text --- lib/v2/transcriptforest/index.js | 116 +++++++ lib/v2/transcriptforest/maintainer.js | 3 + lib/v2/transcriptforest/radar.js | 307 ++++++++++++++++++ lib/v2/transcriptforest/router.js | 3 + .../templates/description.art | 23 ++ website/docs/routes/multimedia.mdx | 59 ++++ 6 files changed, 511 insertions(+) create mode 100644 lib/v2/transcriptforest/index.js create mode 100644 lib/v2/transcriptforest/maintainer.js create mode 100644 lib/v2/transcriptforest/radar.js create mode 100644 lib/v2/transcriptforest/router.js create mode 100644 lib/v2/transcriptforest/templates/description.art diff --git a/lib/v2/transcriptforest/index.js b/lib/v2/transcriptforest/index.js new file mode 100644 index 00000000000000..a83ce775e8be29 --- /dev/null +++ b/lib/v2/transcriptforest/index.js @@ -0,0 +1,116 @@ +const got = require('@/utils/got'); +const cheerio = require('cheerio'); +const { parseDate } = require('@/utils/parse-date'); +const { art } = require('@/utils/render'); +const path = require('path'); + +const bakeTimestamp = (seconds) => { + const hours = Math.floor(seconds / 3600); + const minutes = Math.floor((seconds % 3600) / 60); + const remainingSeconds = Math.floor(seconds % 60); + + const formattedHours = String(hours).padStart(2, '0'); + const formattedMinutes = String(minutes).padStart(2, '0'); + const formattedSeconds = String(remainingSeconds).padStart(2, '0'); + + return `${formattedHours}:${formattedMinutes}:${formattedSeconds}`; +}; + +module.exports = async (ctx) => { + const { channel } = ctx.params; + const limit = ctx.query.limit ? Number.parseInt(ctx.query.limit, 10) : 10; + + const rootUrl = 'https://www.transcriptforest.com'; + + const { data: firstResponse } = await got(rootUrl); + + const data = JSON.parse(firstResponse.match(/({"props".*"scriptLoader":\[]})<\/script>/)?.[1]); + + const buildId = data.buildId; + const defaultLocale = data.defaultLocale; + const channels = data.props.pageProps.listChannel; + const selected = channel ? channels.find((c) => c.channel_id === channel || c.channel_name === channel) : undefined; + + const apiUrl = new URL(`_next/data/${buildId}/en${selected ? `/channel/${selected.channel_id}` : ''}.json`, rootUrl).href; + const currentUrl = new URL(selected ? `${defaultLocale}/channel/${selected.channel_id}` : '', rootUrl).href; + + const { data: response } = await got(apiUrl, { + searchParams: { + channelName: selected ? selected.channel_id : '', + offset: 0, + }, + }); + + let items = response.pageProps.listEpisode.data.slice(0, limit).map((item) => ({ + title: item.episode_name, + link: new URL(`${defaultLocale}/${item.channel_id}/${item.episode_id}`, rootUrl).href, + detailUrl: new URL(`_next/data/${buildId}/${defaultLocale}/${item.channel_id}/${item.episode_id}.json`, rootUrl).href, + description: art(path.join(__dirname, 'templates/description.art'), { + texts: item.episode_description.split(/\n\n/).map((text) => ({ + text, + })), + }), + author: item.channel_name, + guid: item.id, + pubDate: parseDate(item.published_at), + updated: parseDate(item.updated_at), + itunes_item_image: item.episode_cover.split(/\?/)[0], + itunes_duration: item.episode_duration, + enclosure_url: item.source_media, + enclosure_type: 'audio/mpeg', + })); + + items = await Promise.all( + items.map((item) => + ctx.cache.tryGet(item.link, async () => { + const { data: detailResponse } = await got(item.detailUrl); + const { data: textResponse } = await got(detailResponse.pageProps.currentEpisode.ps4_url); + + item.description = + art(path.join(__dirname, 'templates/description.art'), { + audios: [ + { + src: detailResponse.pageProps.currentEpisode.media, + type: 'audio/mpeg', + }, + ], + }) + + item.description + + art(path.join(__dirname, 'templates/description.art'), { + texts: textResponse.map((t) => ({ + startTime: bakeTimestamp(t.startTime), + endTime: bakeTimestamp(t.endTime), + text: t.readOnlyText, + })), + }); + + delete item.detailUrl; + + return item; + }) + ) + ); + + const { data: currentResponse } = await got(currentUrl); + + const $ = cheerio.load(currentResponse); + + const title = $('title').text(); + const image = $('meta[property="og:image"]').prop('content'); + const icon = new URL($('link[rel="apple-touch-icon"]').prop('href'), rootUrl).href; + const author = title.split(/\|/)[0].trim(); + + ctx.state.data = { + item: items, + title, + link: currentUrl, + description: $('meta[name="description"]').prop('content'), + language: $('html').prop('lang'), + image, + icon, + logo: icon, + author, + itunes_author: author, + allowEmpty: true, + }; +}; diff --git a/lib/v2/transcriptforest/maintainer.js b/lib/v2/transcriptforest/maintainer.js new file mode 100644 index 00000000000000..fb0da7f56057f0 --- /dev/null +++ b/lib/v2/transcriptforest/maintainer.js @@ -0,0 +1,3 @@ +module.exports = { + '/:channel?': ['nczitzk'], +}; diff --git a/lib/v2/transcriptforest/radar.js b/lib/v2/transcriptforest/radar.js new file mode 100644 index 00000000000000..db34f20be2dc5c --- /dev/null +++ b/lib/v2/transcriptforest/radar.js @@ -0,0 +1,307 @@ +module.exports = { + 'transcriptforest.com': { + _name: 'Transcript Forest', + www: [ + { + title: 'All', + docs: 'https://docs.rsshub.app/routes/multimedia#transcript-forest', + source: ['/en/channel'], + target: '/transcriptforest', + }, + { + title: 'a16z podcast', + docs: 'https://docs.rsshub.app/routes/multimedia#transcript-forest', + source: ['/en/channel/a16z-podcast'], + target: '/transcriptforest/a16z-podcast', + }, + { + title: "Aarthi and Sriram's Good Time Show", + docs: 'https://docs.rsshub.app/routes/multimedia#transcript-forest', + source: ['/en/channel/aarthi-and-srirams-good-time-show'], + target: '/transcriptforest/aarthi-and-srirams-good-time-show', + }, + { + title: 'Acquired', + docs: 'https://docs.rsshub.app/routes/multimedia#transcript-forest', + source: ['/en/channel/acquired'], + target: '/transcriptforest/acquired', + }, + { + title: 'All-In with Chamath, Jason, Sacks & Friedberg', + docs: 'https://docs.rsshub.app/routes/multimedia#transcript-forest', + source: ['/en/channel/all-in-with-chamath-jason-sacks-friedberg'], + target: '/transcriptforest/all-in-with-chamath-jason-sacks-friedberg', + }, + { + title: 'All the Hacks', + docs: 'https://docs.rsshub.app/routes/multimedia#transcript-forest', + source: ['/en/channel/all-the-hacks'], + target: '/transcriptforest/all-the-hacks', + }, + { + title: 'Breaking Points', + docs: 'https://docs.rsshub.app/routes/multimedia#transcript-forest', + source: ['/en/channel/breaking-points'], + target: '/transcriptforest/breaking-points', + }, + { + title: 'Cartoon Avatars', + docs: 'https://docs.rsshub.app/routes/multimedia#transcript-forest', + source: ['/en/channel/cartoon-avatars'], + target: '/transcriptforest/cartoon-avatars', + }, + { + title: 'Conversations With Coleman', + docs: 'https://docs.rsshub.app/routes/multimedia#transcript-forest', + source: ['/en/channel/conversations-with-coleman'], + target: '/transcriptforest/conversations-with-coleman', + }, + { + title: 'CSPI Podcast', + docs: 'https://docs.rsshub.app/routes/multimedia#transcript-forest', + source: ['/en/channel/cspi-podcast'], + target: '/transcriptforest/cspi-podcast', + }, + { + title: 'Culpable', + docs: 'https://docs.rsshub.app/routes/multimedia#transcript-forest', + source: ['/en/channel/culpable'], + target: '/transcriptforest/culpable', + }, + { + title: 'Dateline NBC', + docs: 'https://docs.rsshub.app/routes/multimedia#transcript-forest', + source: ['/en/channel/dateline-nbc'], + target: '/transcriptforest/dateline-nbc', + }, + { + title: 'Execs', + docs: 'https://docs.rsshub.app/routes/multimedia#transcript-forest', + source: ['/en/channel/execs'], + target: '/transcriptforest/execs', + }, + { + title: 'Exponent', + docs: 'https://docs.rsshub.app/routes/multimedia#transcript-forest', + source: ['/en/channel/exponent'], + target: '/transcriptforest/exponent', + }, + { + title: 'Freakonomics', + docs: 'https://docs.rsshub.app/routes/multimedia#transcript-forest', + source: ['/en/channel/freakonomics'], + target: '/transcriptforest/freakonomics', + }, + { + title: 'Future of StoryTelling', + docs: 'https://docs.rsshub.app/routes/multimedia#transcript-forest', + source: ['/en/channel/future-of-storytelling'], + target: '/transcriptforest/future-of-storytelling', + }, + { + title: 'Gamecraft', + docs: 'https://docs.rsshub.app/routes/multimedia#transcript-forest', + source: ['/en/channel/gamecraft'], + target: '/transcriptforest/gamecraft', + }, + { + title: 'Get WIRED', + docs: 'https://docs.rsshub.app/routes/multimedia#transcript-forest', + source: ['/en/channel/get-wired'], + target: '/transcriptforest/get-wired', + }, + { + title: 'Greymatter', + docs: 'https://docs.rsshub.app/routes/multimedia#transcript-forest', + source: ['/en/channel/greymatter'], + target: '/transcriptforest/greymatter', + }, + { + title: 'How I built this', + docs: 'https://docs.rsshub.app/routes/multimedia#transcript-forest', + source: ['/en/channel/how-I-built-this'], + target: '/transcriptforest/how-I-built-this', + }, + { + title: 'Huberman Lab', + docs: 'https://docs.rsshub.app/routes/multimedia#transcript-forest', + source: ['/en/channel/huberman-lab'], + target: '/transcriptforest/huberman-lab', + }, + { + title: 'ICYMI', + docs: 'https://docs.rsshub.app/routes/multimedia#transcript-forest', + source: ['/en/channel/icymi'], + target: '/transcriptforest/icymi', + }, + { + title: 'In Machines We Trust', + docs: 'https://docs.rsshub.app/routes/multimedia#transcript-forest', + source: ['/en/channel/in-machines-we-trust'], + target: '/transcriptforest/in-machines-we-trust', + }, + { + title: "Invest Like the Best with Patrick O'Shaughnessy", + docs: 'https://docs.rsshub.app/routes/multimedia#transcript-forest', + source: ['/en/channel/invest-like-the-best-with-patrick-o-shaughnessy'], + target: '/transcriptforest/invest-like-the-best-with-patrick-o-shaughnessy', + }, + { + title: 'Joe Rogan Experience Review podcast', + docs: 'https://docs.rsshub.app/routes/multimedia#transcript-forest', + source: ['/en/channel/joe-rogan-experience-review-podcast'], + target: '/transcriptforest/joe-rogan-experience-review-podcast', + }, + { + title: 'Land of Giants', + docs: 'https://docs.rsshub.app/routes/multimedia#transcript-forest', + source: ['/en/channel/land-of-giants'], + target: '/transcriptforest/land-of-giants', + }, + { + title: "Lenny's Podcast: Product | Growth | Career", + docs: 'https://docs.rsshub.app/routes/multimedia#transcript-forest', + source: ['/en/channel/lenny-podcast-product-growth-career'], + target: '/transcriptforest/lenny-podcast-product-growth-career', + }, + { + title: 'Lex Fridman Podcast', + docs: 'https://docs.rsshub.app/routes/multimedia#transcript-forest', + source: ['/en/channel/lex-fridman-podcast'], + target: '/transcriptforest/lex-fridman-podcast', + }, + { + title: 'Making Sense with Sam Harris', + docs: 'https://docs.rsshub.app/routes/multimedia#transcript-forest', + source: ['/en/channel/making-sense-with-sam-harris'], + target: '/transcriptforest/making-sense-with-sam-harris', + }, + { + title: 'Masters of Scale', + docs: 'https://docs.rsshub.app/routes/multimedia#transcript-forest', + source: ['/en/channel/masters-of-scale'], + target: '/transcriptforest/masters-of-scale', + }, + { + title: 'Modern Wisdom', + docs: 'https://docs.rsshub.app/routes/multimedia#transcript-forest', + source: ['/en/channel/modern-wisdom'], + target: '/transcriptforest/modern-wisdom', + }, + { + title: 'Moment of Zen', + docs: 'https://docs.rsshub.app/routes/multimedia#transcript-forest', + source: ['/en/channel/moment-of-zen'], + target: '/transcriptforest/moment-of-zen', + }, + { + title: 'Morbid', + docs: 'https://docs.rsshub.app/routes/multimedia#transcript-forest', + source: ['/en/channel/morbid'], + target: '/transcriptforest/morbid', + }, + { + title: 'My First Million', + docs: 'https://docs.rsshub.app/routes/multimedia#transcript-forest', + source: ['/en/channel/my-first-million'], + target: '/transcriptforest/my-first-million', + }, + { + title: 'Naval', + docs: 'https://docs.rsshub.app/routes/multimedia#transcript-forest', + source: ['/en/channel/naval'], + target: '/transcriptforest/naval', + }, + { + title: 'Newcomer Podcast', + docs: 'https://docs.rsshub.app/routes/multimedia#transcript-forest', + source: ['/en/channel/newcomer-podcast'], + target: '/transcriptforest/newcomer-podcast', + }, + { + title: 'Not investment advice', + docs: 'https://docs.rsshub.app/routes/multimedia#transcript-forest', + source: ['/en/channel/not-investment-advice'], + target: '/transcriptforest/not-investment-advice', + }, + { + title: 'Odd Lots', + docs: 'https://docs.rsshub.app/routes/multimedia#transcript-forest', + source: ['/en/channel/odd-lots'], + target: '/transcriptforest/odd-lots', + }, + { + title: 'On with Kara Swisher', + docs: 'https://docs.rsshub.app/routes/multimedia#transcript-forest', + source: ['/en/channel/on-with-kara-swisher'], + target: '/transcriptforest/on-with-kara-swisher', + }, + { + title: 'Proof: A True Crime Podcast', + docs: 'https://docs.rsshub.app/routes/multimedia#transcript-forest', + source: ['/en/channel/proof-a-true-crime-podcast'], + target: '/transcriptforest/proof-a-true-crime-podcast', + }, + { + title: 'Reply All', + docs: 'https://docs.rsshub.app/routes/multimedia#transcript-forest', + source: ['/en/channel/reply-all'], + target: '/transcriptforest/reply-all', + }, + { + title: 'Revisionist History', + docs: 'https://docs.rsshub.app/routes/multimedia#transcript-forest', + source: ['/en/channel/revisionist-history'], + target: '/transcriptforest/revisionist-history', + }, + { + title: 'Serial', + docs: 'https://docs.rsshub.app/routes/multimedia#transcript-forest', + source: ['/en/channel/serial-podcast'], + target: '/transcriptforest/serial-podcast', + }, + { + title: 'Slow Burn', + docs: 'https://docs.rsshub.app/routes/multimedia#transcript-forest', + source: ['/en/channel/slow-burn'], + target: '/transcriptforest/slow-burn', + }, + { + title: 'StrictlyVC Download', + docs: 'https://docs.rsshub.app/routes/multimedia#transcript-forest', + source: ['/en/channel/strictlyvc-download'], + target: '/transcriptforest/strictlyvc-download', + }, + { + title: 'Stuff You Should Know:', + docs: 'https://docs.rsshub.app/routes/multimedia#transcript-forest', + source: ['/en/channel/stuff-you-should-know'], + target: '/transcriptforest/stuff-you-should-know', + }, + { + title: 'Subversive w/Alex Kaschuta', + docs: 'https://docs.rsshub.app/routes/multimedia#transcript-forest', + source: ['/en/channel/subversive-w-alex-kaschuta'], + target: '/transcriptforest/subversive-w-alex-kaschuta', + }, + { + title: 'TED Radio Hour', + docs: 'https://docs.rsshub.app/routes/multimedia#transcript-forest', + source: ['/en/channel/ted-radio-hour'], + target: '/transcriptforest/ted-radio-hour', + }, + { + title: 'The Bootstrapped Founder', + docs: 'https://docs.rsshub.app/routes/multimedia#transcript-forest', + source: ['/en/channel/the-bootstrapped-founder'], + target: '/transcriptforest/the-bootstrapped-founder', + }, + { + title: 'The Boyscast with Ryan Long', + docs: 'https://docs.rsshub.app/routes/multimedia#transcript-forest', + source: ['/en/channel/the-boyscast-with-ryan-long'], + target: '/transcriptforest/the-boyscast-with-ryan-long', + }, + ], + }, +}; diff --git a/lib/v2/transcriptforest/router.js b/lib/v2/transcriptforest/router.js new file mode 100644 index 00000000000000..79163f9a7d72f9 --- /dev/null +++ b/lib/v2/transcriptforest/router.js @@ -0,0 +1,3 @@ +module.exports = (router) => { + router.get('/:channel?', require('./')); +}; diff --git a/lib/v2/transcriptforest/templates/description.art b/lib/v2/transcriptforest/templates/description.art new file mode 100644 index 00000000000000..c62849a7683ce7 --- /dev/null +++ b/lib/v2/transcriptforest/templates/description.art @@ -0,0 +1,23 @@ +{{ if audios }} + {{ each audios audio }} + {{ if audio?.src }} + + {{ /if }} + {{ /each }} +{{ /if }} + +{{ if texts }} + {{ each texts t }} + {{ if t.startTime && t.endTime }} + {{ t.startTime }} - {{ t.endTime }} + {{ /if }} +

{{ t.text }}

+ {{ /each }} +{{ /if }} \ No newline at end of file diff --git a/website/docs/routes/multimedia.mdx b/website/docs/routes/multimedia.mdx index df83a42914bcea..10a4cf96796123 100644 --- a/website/docs/routes/multimedia.mdx +++ b/website/docs/routes/multimedia.mdx @@ -1135,6 +1135,65 @@ Refer to [https://developers.themoviedb.org/3/getting-started/languages](https:/ +## Transcript Forest {#transcript-forest} + +### Channel {#transcript-forest-channel} + + + | Channel | ID | + | ---------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | + | [All](https://www.transcriptforest.com/en) | | + | [a16z podcast](https://www.transcriptforest.com/en/channel/a16z-podcast) | [a16z-podcast](https://rsshub.app/transcriptforest/a16z-podcast) | + | [Aarthi and Sriram's Good Time Show](https://www.transcriptforest.com/en/channel/aarthi-and-srirams-good-time-show) | [aarthi-and-srirams-good-time-show](https://rsshub.app/transcriptforest/aarthi-and-srirams-good-time-show) | + | [Acquired](https://www.transcriptforest.com/en/channel/acquired) | [acquired](https://rsshub.app/transcriptforest/acquired) | + | [All-In with Chamath, Jason, Sacks & Friedberg](https://www.transcriptforest.com/en/channel/all-in-with-chamath-jason-sacks-friedberg) | [all-in-with-chamath-jason-sacks-friedberg](https://rsshub.app/transcriptforest/all-in-with-chamath-jason-sacks-friedberg) | + | [All the Hacks](https://www.transcriptforest.com/en/channel/all-the-hacks) | [all-the-hacks](https://rsshub.app/transcriptforest/all-the-hacks) | + | [Breaking Points](https://www.transcriptforest.com/en/channel/breaking-points) | [breaking-points](https://rsshub.app/transcriptforest/breaking-points) | + | [Cartoon Avatars](https://www.transcriptforest.com/en/channel/cartoon-avatars) | [cartoon-avatars](https://rsshub.app/transcriptforest/cartoon-avatars) | + | [Conversations With Coleman](https://www.transcriptforest.com/en/channel/conversations-with-coleman) | [conversations-with-coleman](https://rsshub.app/transcriptforest/conversations-with-coleman) | + | [CSPI Podcast](https://www.transcriptforest.com/en/channel/cspi-podcast) | [cspi-podcast](https://rsshub.app/transcriptforest/cspi-podcast) | + | [Culpable](https://www.transcriptforest.com/en/channel/culpable) | [culpable](https://rsshub.app/transcriptforest/culpable) | + | [Dateline NBC](https://www.transcriptforest.com/en/channel/dateline-nbc) | [dateline-nbc](https://rsshub.app/transcriptforest/dateline-nbc) | + | [Execs](https://www.transcriptforest.com/en/channel/execs) | [execs](https://rsshub.app/transcriptforest/execs) | + | [Exponent](https://www.transcriptforest.com/en/channel/exponent) | [exponent](https://rsshub.app/transcriptforest/exponent) | + | [Freakonomics](https://www.transcriptforest.com/en/channel/freakonomics) | [freakonomics](https://rsshub.app/transcriptforest/freakonomics) | + | [Future of StoryTelling](https://www.transcriptforest.com/en/channel/future-of-storytelling) | [future-of-storytelling](https://rsshub.app/transcriptforest/future-of-storytelling) | + | [Gamecraft](https://www.transcriptforest.com/en/channel/gamecraft) | [gamecraft](https://rsshub.app/transcriptforest/gamecraft) | + | [Get WIRED](https://www.transcriptforest.com/en/channel/get-wired) | [get-wired](https://rsshub.app/transcriptforest/get-wired) | + | [Greymatter](https://www.transcriptforest.com/en/channel/greymatter) | [greymatter](https://rsshub.app/transcriptforest/greymatter) | + | [How I built this](https://www.transcriptforest.com/en/channel/how-I-built-this) | [how-I-built-this](https://rsshub.app/transcriptforest/how-I-built-this) | + | [Huberman Lab](https://www.transcriptforest.com/en/channel/huberman-lab) | [huberman-lab](https://rsshub.app/transcriptforest/huberman-lab) | + | [ICYMI](https://www.transcriptforest.com/en/channel/icymi) | [icymi](https://rsshub.app/transcriptforest/icymi) | + | [In Machines We Trust](https://www.transcriptforest.com/en/channel/in-machines-we-trust) | [in-machines-we-trust](https://rsshub.app/transcriptforest/in-machines-we-trust) | + | [Invest Like the Best with Patrick O'Shaughnessy](https://www.transcriptforest.com/en/channel/invest-like-the-best-with-patrick-o-shaughnessy) | [invest-like-the-best-with-patrick-o-shaughnessy](https://rsshub.app/transcriptforest/invest-like-the-best-with-patrick-o-shaughnessy) | + | [Joe Rogan Experience Review podcast](https://www.transcriptforest.com/en/channel/joe-rogan-experience-review-podcast) | [joe-rogan-experience-review-podcast](https://rsshub.app/transcriptforest/joe-rogan-experience-review-podcast) | + | [Land of Giants](https://www.transcriptforest.com/en/channel/land-of-giants) | [land-of-giants](https://rsshub.app/transcriptforest/land-of-giants) | + | [Lenny's Podcast: Product \| Growth \| Career](https://www.transcriptforest.com/en/channel/lenny-podcast-product-growth-career) | [lenny-podcast-product-growth-career](https://rsshub.app/transcriptforest/lenny-podcast-product-growth-career) | + | [Lex Fridman Podcast](https://www.transcriptforest.com/en/channel/lex-fridman-podcast) | [lex-fridman-podcast](https://rsshub.app/transcriptforest/lex-fridman-podcast) | + | [Making Sense with Sam Harris](https://www.transcriptforest.com/en/channel/making-sense-with-sam-harris) | [making-sense-with-sam-harris](https://rsshub.app/transcriptforest/making-sense-with-sam-harris) | + | [Masters of Scale](https://www.transcriptforest.com/en/channel/masters-of-scale) | [masters-of-scale](https://rsshub.app/transcriptforest/masters-of-scale) | + | [Modern Wisdom](https://www.transcriptforest.com/en/channel/modern-wisdom) | [modern-wisdom](https://rsshub.app/transcriptforest/modern-wisdom) | + | [Moment of Zen](https://www.transcriptforest.com/en/channel/moment-of-zen) | [moment-of-zen](https://rsshub.app/transcriptforest/moment-of-zen) | + | [Morbid](https://www.transcriptforest.com/en/channel/morbid) | [morbid](https://rsshub.app/transcriptforest/morbid) | + | [My First Million](https://www.transcriptforest.com/en/channel/my-first-million) | [my-first-million](https://rsshub.app/transcriptforest/my-first-million) | + | [Naval](https://www.transcriptforest.com/en/channel/naval) | [naval](https://rsshub.app/transcriptforest/naval) | + | [Newcomer Podcast](https://www.transcriptforest.com/en/channel/newcomer-podcast) | [newcomer-podcast](https://rsshub.app/transcriptforest/newcomer-podcast) | + | [Not investment advice](https://www.transcriptforest.com/en/channel/not-investment-advice) | [not-investment-advice](https://rsshub.app/transcriptforest/not-investment-advice) | + | [Odd Lots](https://www.transcriptforest.com/en/channel/odd-lots) | [odd-lots](https://rsshub.app/transcriptforest/odd-lots) | + | [On with Kara Swisher](https://www.transcriptforest.com/en/channel/on-with-kara-swisher) | [on-with-kara-swisher](https://rsshub.app/transcriptforest/on-with-kara-swisher) | + | [Proof: A True Crime Podcast](https://www.transcriptforest.com/en/channel/proof-a-true-crime-podcast) | [proof-a-true-crime-podcast](https://rsshub.app/transcriptforest/proof-a-true-crime-podcast) | + | [Reply All](https://www.transcriptforest.com/en/channel/reply-all) | [reply-all](https://rsshub.app/transcriptforest/reply-all) | + | [Revisionist History](https://www.transcriptforest.com/en/channel/revisionist-history) | [revisionist-history](https://rsshub.app/transcriptforest/revisionist-history) | + | [Serial](https://www.transcriptforest.com/en/channel/serial-podcast) | [serial-podcast](https://rsshub.app/transcriptforest/serial-podcast) | + | [Slow Burn](https://www.transcriptforest.com/en/channel/slow-burn) | [slow-burn](https://rsshub.app/transcriptforest/slow-burn) | + | [StrictlyVC Download](https://www.transcriptforest.com/en/channel/strictlyvc-download) | [strictlyvc-download](https://rsshub.app/transcriptforest/strictlyvc-download) | + | [Stuff You Should Know:](https://www.transcriptforest.com/en/channel/stuff-you-should-know) | [stuff-you-should-know](https://rsshub.app/transcriptforest/stuff-you-should-know) | + | [Subversive w/Alex Kaschuta](https://www.transcriptforest.com/en/channel/subversive-w-alex-kaschuta) | [subversive-w-alex-kaschuta](https://rsshub.app/transcriptforest/subversive-w-alex-kaschuta) | + | [TED Radio Hour](https://www.transcriptforest.com/en/channel/ted-radio-hour) | [ted-radio-hour](https://rsshub.app/transcriptforest/ted-radio-hour) | + | [The Bootstrapped Founder](https://www.transcriptforest.com/en/channel/the-bootstrapped-founder) | [the-bootstrapped-founder](https://rsshub.app/transcriptforest/the-bootstrapped-founder) | + | [The Boyscast with Ryan Long](https://www.transcriptforest.com/en/channel/the-boyscast-with-ryan-long) | [the-boyscast-with-ryan-long](https://rsshub.app/transcriptforest/the-boyscast-with-ryan-long) | + + ## U3C3 {#u3c3} ### Keyword Search {#u3c3-keyword-search}