{"id":26501922,"url":"https://github.com/yaotutu/folder2podcast","last_synced_at":"2026-02-11T02:21:14.026Z","repository":{"id":274281051,"uuid":"922441297","full_name":"yaotutu/folder2podcast","owner":"yaotutu","description":"把任何音频变成私人播客 - 上传本地音频或粘贴视频链接，自动生成 RSS，在任意播客客户端订阅收听。适合离线听书、本地音乐管理、视频课程转音频。","archived":false,"fork":false,"pushed_at":"2026-01-08T08:25:42.000Z","size":29787,"stargazers_count":160,"open_issues_count":1,"forks_count":10,"subscribers_count":5,"default_branch":"main","last_synced_at":"2026-01-09T08:57:24.677Z","etag":null,"topics":["podcast","rss"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/yaotutu.png","metadata":{"files":{"readme":"README.en.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-01-26T08:01:57.000Z","updated_at":"2026-01-05T00:55:07.000Z","dependencies_parsed_at":"2025-02-10T12:26:46.056Z","dependency_job_id":"953c7630-2a86-499f-baf5-8b4de92fc299","html_url":"https://github.com/yaotutu/folder2podcast","commit_stats":null,"previous_names":["yaotutu/folder2podcast"],"tags_count":10,"template":false,"template_full_name":null,"purl":"pkg:github/yaotutu/folder2podcast","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yaotutu%2Ffolder2podcast","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yaotutu%2Ffolder2podcast/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yaotutu%2Ffolder2podcast/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yaotutu%2Ffolder2podcast/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/yaotutu","download_url":"https://codeload.github.com/yaotutu/folder2podcast/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yaotutu%2Ffolder2podcast/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29325763,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-11T02:08:56.257Z","status":"ssl_error","status_checked_at":"2026-02-11T02:08:51.338Z","response_time":97,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["podcast","rss"],"created_at":"2025-03-20T17:02:09.813Z","updated_at":"2026-02-11T02:21:13.997Z","avatar_url":"https://github.com/yaotutu.png","language":"TypeScript","funding_links":[],"categories":["TypeScript"],"sub_categories":[],"readme":"[![SVG Banners](https://svg-banners.vercel.app/api?type=rainbow\u0026text1=Folder2Podcast📻\u0026width=800\u0026height=400)](https://github.com/Akshay090/svg-banners)\n\n# 🎙️ Folder2Podcast RSS\n\n\u003e Convert local audio folders to private podcast RSS feeds with one command - Zero intrusion, No side effects\n\n[中文版](README.md)\n\n## Table of Contents\n- [🎙️ Folder2Podcast RSS](#️-folder2podcast-rss)\n  - [Table of Contents](#table-of-contents)\n  - [Background](#background)\n  - [✨ Features](#-features)\n    - [📱 Web Interface](#-web-interface)\n    - [🎯 Other Features](#-other-features)\n  - [🚀 Quick Start](#-quick-start)\n    - [Docker Deployment (Recommended)](#docker-deployment-recommended)\n  - [Docker Image Tags](#docker-image-tags)\n  - [📦 Directory Structure](#-directory-structure)\n    - [Configuration File Location](#configuration-file-location)\n  - [⚙️ Configuration](#️-configuration)\n    - [Environment Variables](#environment-variables)\n    - [podcast.json Configuration](#podcastjson-configuration)\n  - [🎨 Advanced Features](#-advanced-features)\n  - [📱 Client Support](#-client-support)\n    - [Supported Podcast Clients](#supported-podcast-clients)\n    - [Usage Flow](#usage-flow)\n    - [RSS Best Practices](#rss-best-practices)\n  - [Troubleshooting](#troubleshooting)\n  - [📋 Support \\\u0026 Feedback](#-support--feedback)\n  - [Changelog](#changelog)\n\n## Background\n\nPodcast RSS is a powerful audio distribution standard that provides:\n\n- 🔖 Complete playback progress tracking\n- 🎯 Precise resume playback functionality\n- 🔄 Cross-device listening history sync\n- 📱 Multi-platform listening support\n- 🎨 Rich media information display\n\nFolder2Podcast RSS lets you easily convert local audio folders into private podcast RSS feeds, enjoying all the advanced features of professional podcast clients:\n\n- 🎧 Listen using your favorite podcast apps (like Apple Podcasts, Pocket Casts)\n- 📱 Continue from where you left off on any device\n- 🔄 Automatically sync listening history across devices\n- 📚 Systematically manage your audiobook library\n- 🎯 Smart bookmarking for every audio file\n\nJust one command to deploy, transforming your local audio into private podcast feeds instantly.\n\n## ✨ Features\n\n### 📱 Web Interface\nThe project provides a user-friendly web interface that allows users to:\n- View all available podcast sources\n- Copy subscription URLs with one click\n- One-click subscription support for multiple podcast clients:\n  - Apple Podcasts\n  - Overcast\n  - Pocket Casts\n  - Castro\n  - Moon FM\n  - More clients coming soon...\n\n![Web Interface Preview](docs/images/web-interface.png)\n\n### 🎯 Other Features\n- Smart filename processing\n- Automatic serialization\n- Cover image management\n- Multi-device sync\n\nFor detailed information, please refer to [Advanced Guide](docs/advanced-guide.en.md).\n\n## 🚀 Quick Start\n\n### Docker Deployment (Recommended)\n\n1. **Preparation**\n   - Install Docker\n   - Prepare audio directories (organized by podcast content)\n   - Standardize filename format (e.g., 01-Chapter1.mp3, Episode02.mp3)\n\n⚠️ **Important: BASE_URL Configuration**\n\nWhen deploying to a server, you must properly configure the BASE_URL environment variable, which affects:\n- Audio file links in RSS feed\n- Cover image links\n- All static resource access paths\n\nConfiguration examples:\n```bash\n# For local testing\nBASE_URL=http://localhost:3000\n\n# For server deployment (replace with your actual server IP or domain)\nBASE_URL=http://192.168.55.222:3000\n# or\nBASE_URL=http://your-domain.com\n```\n\nImportant notes:\n- BASE_URL must include protocol prefix (http:// or https://)\n- Include port number if using custom port\n- Don't add trailing slash '/'\n- Ensure the address is accessible from client devices (like podcast apps)\n\n2. **Launch Service**\n\n   Option 1: Direct Docker command\n   ```bash\n   docker run -d \\\n     -p 3000:3000 \\\n     -v /path/to/audiobooks:/podcasts \\\n     -e PORT=3000 \\\n     -e BASE_URL=http://your-server-ip:3000 \\\n     -e PUID=$(id -u) \\\n     -e PGID=$(id -g) \\\n     yaotutu/folder2podcast\n   ```\n\n   Option 2: Using Docker Compose (Recommended)\n   ```yaml\n   # docker-compose.yml\n   version: '3.8'\n   services:\n     folder2podcast:\n       image: yaotutu/folder2podcast\n       ports:\n         - \"3000:3000\"\n       volumes:\n         - ./audiobooks:/podcasts:ro  # Mount in read-only mode\n       environment:\n         - PORT=3000\n         - AUDIO_DIR=/podcasts\n         - BASE_URL=http://your-server-ip:3000\n         - PUID=1000  # Replace with your user ID\n         - PGID=1000  # Replace with your group ID\n       restart: unless-stopped\n   ```\n\n   \u003e **Permission Note**:\n   \u003e - Sometimes Docker container might have trouble accessing your audio files\n   \u003e - In such cases, you need to set `PUID` and `PGID` environment variables\n   \u003e - These values should match the owner ID of your audio folder\n   \u003e - On Mac/Linux, simply run `id -u` and `id -g` in terminal to get these values\n   \u003e - Once set correctly, the app will be able to access your audio files normally\n\n3. **Verify Deployment**\n   - Visit `http://localhost:3000/podcasts` to confirm service is running\n   - Check if podcast list displays correctly\n   - Test audio file access\n\n## Docker Image Tags\n\n- `yaotutu/folder2podcast:main` - Development version, synced with main branch, includes latest features\n- `yaotutu/folder2podcast:latest` - Stable version, tested and released, recommended for production\n\n## 📦 Directory Structure\n\nEach podcast folder can contain its own `podcast.json` configuration file to customize that podcast's presentation and behavior. This design allows different settings for each podcast series.\n\n### Configuration File Location\n```\naudiobooks/\n├── podcast-series-1/\n│   ├── 01-chapter1.mp3\n│   └── podcast.json    # Independent config for series 1\n└── podcast-series-2/\n    ├── 01.intro.mp3\n    └── podcast.json    # Independent config for series 2\n```\n\n## ⚙️ Configuration\n\n### Environment Variables\n\nThe system supports multiple environment variables for customization. Here's the complete list:\n\n| Variable       | Description                        | Default                 | Example                      |\n| -------------- | ---------------------------------- | ----------------------- | ---------------------------- |\n| `AUDIO_DIR`    | Audio files root directory         | `./audio`               | `/path/to/audiobooks`        |\n| `PORT`         | Server listening port              | `3000`                  | `8080`                       |\n| `BASE_URL`     | Server base URL for RSS feed links | `http://localhost:PORT` | `http://192.168.55.222:3000` |\n| `TITLE_FORMAT` | Episode title display format       | `full`                  | `clean` or `full`            |\n| `PUID`         | Audio folder owner ID              | `1000`                  | Run `id -u` to get           |\n| `PGID`         | Audio folder group ID              | `1000`                  | Run `id -g` to get           |\n\nDetailed description:\n\n1. **AUDIO_DIR**\n   - Purpose: Specify root directory for audio files\n   - Default: audio folder in current directory\n   - Note: Directory must have read permissions\n\n2. **PORT**\n   - Purpose: Specify server listening port\n   - Default: 3000\n   - Note: Service won't start if port is occupied\n\n3. **BASE_URL**\n   - Purpose: Generate URLs in RSS feed\n   - Default: `http://localhost:port`\n   - Importance: Must be set correctly to ensure audio files are accessible\n   - Format: Must include protocol (http/https)\n\n4. **TITLE_FORMAT**\n   - Purpose: Control episode title display format\n   - Default: `full` (keep complete filename)\n   - Options:\n     * `full`: Keep complete filename (without extension)\n     * `clean`: Remove number prefix and separators\n\nUsage example:\n\n```bash\n# Docker run example\ndocker run -d \\\n  -p 3000:3000 \\\n  -v /audiobooks:/podcasts \\\n  -e AUDIO_DIR=/podcasts \\\n  -e PORT=3000 \\\n  -e BASE_URL=http://192.168.55.222:3000 \\\n  -e TITLE_FORMAT=full \\\n  yaotutu/folder2podcast\n```\n\nConfiguration priority:\n- Environment variables \u003e Default values\n- podcast.json config \u003e Environment variables (for specific podcasts)\n\n### podcast.json Configuration\n```json\n{\n  \"title\": \"Podcast Title\",\n  \"description\": \"Podcast Description\",\n  \"author\": \"Author Name\",\n  \"email\": \"author@example.com\",\n  \"language\": \"en-us\",\n  \"category\": \"Technology\",\n  \"explicit\": false,\n  \"websiteUrl\": \"https://example.com\",\n  \"titleFormat\": \"clean\",\n  \"episodeNumberStrategy\": \"first\",  // Episode number extraction strategy: prefix (default), suffix, first, last, or { pattern: \"regex\" }\n  \"useMTime\": false  // Whether to use file creation time as publish date, defaults to false\n}\n```\n\n\u003e 📝 **Time Management Note**:\n\u003e - When `useMTime` is `false` (default):\n\u003e   - Files with numbers use number-based publish dates\n\u003e   - Files without numbers use file creation time\n\u003e - When `useMTime` is `true`:\n\u003e   - All files use file creation time as publish date\n\u003e   - Ignores number information in filenames\n\u003e - For detailed information, refer to [Advanced Guide](docs/advanced-guide.en.md)\n\n## 🎨 Advanced Features\n\n## 📱 Client Support\n\n### Supported Podcast Clients\n\nAlmost all podcast clients that support custom RSS feeds work:\n\n- Apple Podcasts (iOS, Mac)\n- Pocket Casts (All platforms)\n- Overcast (iOS)\n- Castro (iOS)\n- Google Podcasts (Android, Web)\n- AntennaPod (Android)\n\n### Usage Flow\n\n1. **Get Subscription Link**\n   - Visit `http://your-server:3000/podcasts`\n   - Find the podcast series you want to subscribe to\n   - Copy the corresponding RSS Feed URL\n\n2. **Add to Podcast Client**\n   - Open your preferred podcast client\n   - Find \"Add Podcast\" or \"Add RSS Feed\"\n   - Paste your Feed URL\n   - Wait for content to sync\n\n3. **Start Using**\n   - All episodes will automatically sync to the client\n   - Listening progress syncs across devices\n   - Supports background download and offline playback\n   - Can add chapter notes (supported by some clients)\n\n### RSS Best Practices\n\n1. **Content Organization**\n   - Use clear folder structure\n   - Maintain consistent file naming\n   - Add high-quality cover images (recommended 1400x1400px)\n\n2. **Performance Optimization**\n   - Control the number of audio files per folder\n   - Use mp3 format for best compatibility\n   - Configure correct BASE_URL to ensure accessibility\n\n## Troubleshooting\n\n## 📋 Support \u0026 Feedback\n\n- Found a bug? [Submit Issue](https://github.com/your-repo/folder2podcast/issues)\n- Have suggestions? [Join Discussion](https://github.com/your-repo/folder2podcast/discussions)\n- Want to contribute? [Submit PR](https://github.com/your-repo/folder2podcast/pulls)\n\n## Changelog\n\nView complete update history in [CHANGELOG.md](CHANGELOG.md)\n\n\u003cdiv align=\"center\"\u003e\n\n\u003ctable\u003e\n  \u003ctr\u003e\n    \u003ctd align=\"center\"\u003e\n      \u003cimg src=\"docs/images/wechat.jpg\" width=\"280\" alt=\"WeChat Group\"\u003e\n      \u003cbr\u003e\n      👆 Scan QR code to join our WeChat group for beta testing!\n    \u003c/td\u003e\n    \u003ctd align=\"center\"\u003e\n      \u003ca href=\"https://www.producthunt.com/posts/folder2podcast-rss?embed=true\"\u003e\n        \u003cimg src=\"https://api.producthunt.com/widgets/embed-image/v1/featured.svg?post_id=826261\u0026theme=light\" \n          alt=\"Folder2Podcast RSS - Local folders to RSS podcast feeds\" \n          width=\"250\" height=\"54\"\u003e\n      \u003c/a\u003e\n      \u003cbr\u003e\n      \u003ca href=\"https://starchart.cc/yaotutu/folder2podcast\"\u003e\n        \u003cimg src=\"https://starchart.cc/yaotutu/folder2podcast.svg\" alt=\"Stargazers over time\" width=\"500\"\u003e\n      \u003c/a\u003e\n    \u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n\u003c/div\u003e\n\n### 1. Podcast List API\n- Access `/podcasts` to get all available podcasts\n- Returns detailed information including title, description, subscription URLs\n- Feed URLs include complete access addresses ready for subscription\n\n### 2. Resource Access\n- Podcast cover: `/audio/podcast-name/cover.jpg`\n- Audio files: `/audio/podcast-name/episode.mp3`\n- Default resources: `/image/default-cover.jpg`","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyaotutu%2Ffolder2podcast","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fyaotutu%2Ffolder2podcast","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyaotutu%2Ffolder2podcast/lists"}