WordPress podcast plugin with AI pipeline: automatic transcription, AI summaries, Podcasting 2.0 chapters, RSS feeds, and Gutenberg blocks.
Information
Author:
ROBOTSTXTDownload
Price:
€120.00Requirements
Version:
2.3.0WordPress:
7.0–
7.1PHP >=
8.2Changelog
2.3.0
_Release date: 2026-08-11_
Highlights
- Chart.js charts and world map for statistics, IAB-aligned download filtering, daily rollup tables, and 3-tier configurable data retention.
Added
- Chart.js integration — line charts for monthly/daily download trends (interactive tooltips, smooth curves), doughnut charts for client breakdowns, replacing inline SVG sparklines.
- World map (jsVectorMap) for country breakdowns — chloropleth view shaded by download count with hover tooltips.
- IAB-aligned filtering — 60-second byte-threshold filter (
IabConfig), expanded and filterable bot/crawler detection list,is_iab_compliantflag stored on raw events. - Daily rollup tables —
podcast_download_daily,_daily_country,_daily_clientfor fast pre-aggregated queries at day/episode/country/client granularity. - Platform stats schema —
podcast_platform_statsandpodcast_platform_episode_maptables (infrastructure for Spotify/Apple CSV import). - 3-tier data retention — raw events (384 days), daily rollups (3650 days / ~10 years), monthly rollups (36 months). All configurable in Settings → Stats. 0 = unlimited.
Changed
- Stats page and REST endpoint queries now read from daily rollup tables instead of the raw events table.
- Stats seeder (
wp podcast stats seed) now runs the Aggregator automatically and populates daily country/client rollup tables. - Database schema version bumped to 3.
Compatibility
- WordPress: 7.0 – 7.1
- PHP: 8.2 – 8.5
2.2.0
_Release date: 2026-08-11_
Highlights
- Per-episode statistics drill-down and custom date-range filtering.
Added
- Per-episode statistics detail view — each episode in the “All episodes” table has a “View” button linking to a detail page with all-time / 7-day / 30-day totals, monthly and daily trend charts, and top countries/clients.
- Per-month/day episode breakdown — each month/day row in the trend tables has a “View” button showing which episodes drove downloads in that period, with top countries/clients.
- Custom date-range filter — date-range picker on the Stats overview with episodes, countries, and clients scoped to the chosen range.
Compatibility
- WordPress: 7.0 – 7.1
- PHP: 8.2 – 8.5
2.1.0
_Release date: 2026-08-11_
Highlights
- Statistics dashboard redesign, customizable AI prompts, manual companion blog post creation, and a corrected review-to-publish flow.
Added
- Statistics page redesign — inline SVG line charts (no JS library dependency), two-pane layout with monthly (trailing 12 months) and daily (last 12 days) trends, zero-filled calendar axes, top episodes/countries/clients each split into trailing-12-months vs last-month tables, and a full “All episodes” table with date, episode number, channel/season, and lifetime downloads. Dates rendered via the site’s Settings → General date format.
- Customizable AI prompts — 3-tier priority (channel override → general setting → built-in default) for the summary/chapters and blog-post prompts. Settings → AI tab and Channel edit screen expose textareas with “Reset to default” buttons and collapsible default-prompt previews. The
{paragraphs}placeholder is supported; the strict JSON response contract is always auto-appended (non-editable) so processing can never break parsing. - Companion blog post — manual creation — a dedicated “Companion Blog Post” meta box appears on approved episodes with a “Create blog post” button. Generation uses the episode’s final title (post-approval), so the slug is correct. Once created: “Edit blog post” link + “Regenerate” button (while still a draft). New REST endpoint
POST /episode/{id}/generate-blog-post. “Generating…” visual feedback during the OpenAI call. - Quick Add “Process now” button — AJAX force-retry on the Quick Add progress page, bypassing Action Scheduler’s exponential backoff for immediate feedback on transient failures.
Changed
- Approve/Discard no longer auto-publishes — both actions now save the episode as a draft instead of publishing immediately, so a human always takes a separate explicit step (set publish date, add featured image, etc.) before going live. Button labels updated: “Approve and Draft” and “Discard AI and Save as Draft”. The public RSS feed, stats table, and front-end episode list correctly exclude draft episodes.
- Blog post generation moved out of Phase B — the automatic
maybe_generate_blog_post()step was removed; the global “generate by default” toggle and per-episode toggle meta were removed. Blog post creation is now exclusively manual via the button above. - CLAUDE.md REST endpoint table updated to reflect the new approve/discard draft behavior and the new generate-blog-post route.
Fixed
- Quick Add media picker not working —
QuickAddPage::enqueue_admin_assets()compared the admin hook suffix against a hardcoded string that didn’t match what WordPress generates for CPT submenu pages. Now captures the actual hook returned byadd_submenu_page()(same pattern already used bySettingsPageandImportPage). strip_tags(null)deprecation on Settings page via CPT URL —StatsPage::register()calledadd_submenu_page()synchronously duringinitinstead of deferring to theadmin_menuaction, registering the Statistics submenu before WordPress built the CPT’s own default submenu items. WordPress then wrongly promoted Statistics as the menu’s “real parent”, breaking title resolution for every page under the FrequencIA menu when accessed viaedit.php?post_type=podcast_episode&page=.... Fixed by movingadd_submenu_page()into anadmin_menucallback (matching every other admin page class in the plugin).
Tests
- 698 tests, PHPCS + PHPStan L9 clean, preflight 6/6 PASS.
- New test files:
StatsPageTest,PromptSettingsTest. Updated:QuickAddPageTest,EpisodeMetaBoxTest,EpisodeActionsEndpointTest,PhaseBTest,SummaryClientTest,ChannelFieldsTest,SettingsPageTest,EpisodeMetaTest. - Added
http_callscapture andnumber_format_i18n()stub to test bootstrap.
Compatibility
- WordPress: 7.0 – 7.1
- PHP: 8.2 – 8.5
- MariaDB: 11.4+
i18n
- 604 strings in .pot (was 539). .po files synced via msgmerge. .mo files compiled. 66 untranslated strings pending translation (es_ES, ca).
2.0.1
_Release date: 2026-08-10_
Highlights
- Security hardening, documentation restructure, and a dev-dependency CVE fix.
Security
EpisodeActionsEndpoint::save_chapters()— addedis_safe_upload_path()containment check (validate_file()+ uploads-basedir prefix match) before everyfile_put_contents()call. Defense-in-depth against path traversal on both the existing-attachment and new-attachment branches.
Changed
readme.txtrestructured to match the project template: changelog trimmed to 3 latest versions + link tochangelog.txt; addedUsing the pluginsection (WP-CLI commands + REST API table); added
PODCAST_TRANSCRIBE_MODEL to Extra Configurations; updated Compliance section with WordPress APIs Security + Plugin Check links; fixed FAQ answer about JavaScript builds.
CLAUDE.mdCurrent version section updated from stale v1.7.0 to v2.0.0 with full release history (v1.6.0 – v2.0.0).
Fixed
- CVE-2026-67434 in
squizlabs/php_codesniffer(OS command injection). Dev-only dependency updated 3.13.5 → 3.13.6.
Compatibility
- WordPress: 7.0 – 7.1
- PHP: 8.2 – 8.5
- MariaDB: 11.4+
Tests
- PHPCS: 0 errors, 0 warnings.
- PHPStan level 9: 0 errors.
- PHPUnit: 657 tests, 0 failures (15 skipped: integration).
- Preflight: 6/6 PASS.
2.0.0
_Release date: 2026-08-01_
Highlights
- Dual-call transcription: gpt-transcribe for a higher-quality summary transcript, Whisper retained for subtitles and chapter timing.
Added
- Dual-call transcription pipeline — Phase A sends the audio to
gpt-transcribe(content layer) in addition to Whisper (timing layer). Subtitles and chapter timestamps are unchanged. - Transcription-model opt-out — Settings → AI and the
PODCAST_TRANSCRIBE_MODELconstant (defaultgpt-transcribe). Set towhisper-1to skip the second transcription (single-call, lower cost). - Per-channel transcription keywords — host names, sponsors, products, and recurring topics passed to
gpt-transcribeto improve recognition.
Changed
_podcast_transcript_textnow stores the gpt-transcribe plain text; Whisper segment timestamps are stored separately in_podcast_chapter_anchors. Pre-2.0.0 and importer episodes continue to work unchanged.
Security
- GptTranscribeClient enforces mutually-exclusive
language/languages; keywords sanitized to single-line, tag-free, capped values.
Compatibility
- WordPress: 7.0 · PHP: 8.2 – 8.5 · MariaDB: 11.4+
Tests
- 657 tests, PHPCS + PHPStan L9 clean.
1.11.3
_Release date: 2026-07-28_
Changed
- Clarified title prefix descriptions in Settings and ChannelFields: no placeholders needed, text only (e.g. “LR”). The episode number is automatic.
Compatibility
- WordPress: 7.0 · PHP: 8.2 – 8.5 · MariaDB: 11.4+
Tests
- 621 tests, PHPCS + PHPStan L9 clean, preflight 6/6 PASS.
1.11.2
_Release date: 2026-07-28_
Highlights
- Subscribe bar redesign, SSP stats date fix, title prefix hierarchy.
Added
- Subscribe bar horizontal layout + configurable placement. Links now render as a horizontal flex row (logos on one line, wraps on narrow screens). New placement setting: above player / below player / hidden. Global option + per-channel override.
Fixed
- SSP stats import dates. SSP stores
dateas a Unix timestamp integer, not a MySQL datetime.build_timestamp()now detects pure-digit values and converts viagmdate(). - Title prefix parent hierarchy.
resolve_prefix()now walks the channel parent chain (child → parent → … → global) instead of checking only the first assigned channel.
Compatibility
- WordPress: 7.0 · PHP: 8.2 – 8.5 · MariaDB: 11.4+
Tests
- 621 tests, PHPCS + PHPStan L9 clean, preflight 6/6 PASS.
1.11.1
_Release date: 2026-07-28_
Highlights
- AJAX batched statistics import with live progress bar, date validation fix, TODO cleanup.
Added
- AJAX statistics import.
StatsImportAjaxdrives batched imports (5000 events per request) over admin-ajax with a live progress bar — no more timeouts on large SSP catalogs. Mirrors the catalog importer pattern.
Fixed
- Statistics date validation. Invalid/unparseable timestamps are now rejected (event skipped) instead of writing
0000-00-00to MySQL.build_timestamp()validates viastrtotime()+gmdate(). - TODO cleanup. All completed items marked; stale entries removed.
Compatibility
- WordPress: 7.0 · PHP: 8.2 – 8.5 · MariaDB: 11.4+
Tests
- 621 tests, PHPCS + PHPStan L9 clean, preflight 6/6 PASS.
1.11.0
_Release date: 2026-07-28_
Highlights
- AI-generated companion blog post, brand SVG logos for subscribe links, and stats importer column-detection fix.
Added
- AI companion blog post. Phase B optionally generates a native WordPress draft
postfrom the transcript — a ready-to-edit article (show notes, recap, SEO landing page) sitting alongside the episode. Toggle: global default in Settings → AI (“Companion blog post”), per-episode override via_podcast_generate_blog_post. Prompt is filterable (frequencia_ai_blog_post_prompt). Re-run safe: updates draft content, never touches published posts. Traceability:_podcast_blog_post_id+_podcast_source_episode. - Brand SVG logos for Apple Podcasts, Spotify, iVoox, Amazon Music, and RSS in the subscribe bar. Platform definitions now support an optional
svgkey; the renderer uses it when available, falls back to the letter-circle for platforms without a brand icon.
Fixed
- Statistics importer column detection. SSP stats table schemas differ across versions (
idvsstat_id,event_date+event_timevsdate). The importer now detects the PK and date column names at runtime usingSELECTwith dynamic access. Default batch limit 5000 to avoid timeout on large catalogs.
Compatibility
- WordPress: 7.0 · PHP: 8.2 – 8.5 · MariaDB: 11.4+
Tests
- 621 tests, PHPCS + PHPStan L9 clean, preflight 6/6 PASS.
1.10.1
_Release date: 2026-07-28_
Highlights
- Statistics importer (SSP → FrequencIA), full-reset pipeline button, and ghost CPT for deactivated SSP.
Added
- Statistics importer (SSP). Reads from
wp_ssp_stats, maps episode IDs via the catalog importer’s IdMap, writes throughTracker::write(). Cursor-based idempotency. CLI:wp podcast stats import-stats ssp [--limit=N] [--aggregate]. Admin panel: detection + import button on the Import page. - “Full reset” button. REST endpoint clears all AI meta, cancels AS jobs, re-queues the full pipeline (Phase A → B → chapters).
- Ghost
podcastCPT. Registers a minimal hidden CPT when SSP data exists but SSP is deactivated, silencingmap_meta_capnotices.
Fixed
map_meta_capnotice for orphaned SSPpodcastpost type.- Admin menu: Add Person submenu highlighting works.
Changed
- Composer patches: PHPStan 2.2.6, WPCS 3.4.1.
bin/deploy.shhardened.
Known issues
- Admin menu highlighting for Channels/Seasons taxonomy pages unresolved on WP 7.0. Deferred.
Compatibility
- WordPress: 7.0 · PHP: 8.2 – 8.5 · MariaDB: 11.4+
Tests
- 618 tests, PHPCS + PHPStan L9 clean, preflight 6/6 PASS.
1.10.0
_Release date: 2026-07-27_
Highlights
- Subscribe links bar above the player on single-episode pages, and cover-image validation surfaced at the episode editor and import log.
Added
- Subscribe links. Per-channel and global subscribe URLs (Apple Podcasts, Spotify, iVoox, YouTube Music, Amazon Music, Pocket Casts, Overcast, RSS) rendered as a “Subscribe” block above the audio/video players on single-episode pages. Three link styles: text only, icons only, or icons + text. Defaults: brand-coloured circle + first letter per platform (RSS gets the classic fan icon). Per-channel override; RSS auto-fills from the channel feed URL. Platform list and icons are filterable (
frequencia_subscribe_platforms,frequencia_subscribe_icon). New Settings → Subscribe tab for global URLs; new “Subscribe Links” section in ChannelFields. - Cover image validation. New
MediaCoverValidatorreads the cached attachment metadata and checks Apple Podcasts specs: JPEG/PNG MIME, 1:1 aspect ratio, ≥1400 px minimum, ≤500 KB recommendation. Warnings are surfaced as an admin notice on the episode edit screen and asWARNentries in the import log.MediaHooks::META_constants thatCoverValidatorreads are now public.
Changed
bin/deploy.sh: hardens the post-deploycomposer installby force-registering PHPCSinstalled_paths— the--no-dev+ restore cycle was silently losing the WPCS standards registration.AGENTS-deploy.md: documented that release ZIPs must be extracted and inspected under/tmp/, never inside the live plugin directory.
Fixed
composer.json: restored theallow-plugins.dealerdirect/phpcodesniffer-composer-installerconfig that was lost during an earlier tooling reinstall.
Compatibility
- WordPress: 7.0
- PHP: 8.2 – 8.5
- MariaDB: 11.4+
Tests
- PHPCS: 0 errors, 0 warnings. PHPStan level 9: 0 errors. PHPUnit: 610 tests, 0 failures (1 pre-existing skip). Preflight: 6/6 PASS. AI audit:
docs/audit-pre-deploy-1.10.0.md.
1.9.3
_Release date: 2026-07-27_
Highlights
- Statistics retention polish, full i18n coverage (es + ca), CBR admin note for source MP3s, and five catalog-importer improvements. Includes the v1.9.2-prep audit fixes (uninstall cleanup, deactivation hook).
Added
- Statistics retention pruning. Daily Action Scheduler job
frequencia_stats_prune(spec §6) deletes raw download events from{prefix}podcast_downloadolder than the configured TTL (default 90 days;0= retain forever). ChunkedDELETE ... LIMIT 50000per run. Monthly rollup and per-episode postmeta are never touched. Pruning is gated by the opt-in (no-op while statistics are disabled). - Settings → Stats tab. Opt-in checkbox (
podcast_stats_enabled) and retention-days input (podcast_stats_retention_days, 0–3650) now in the GUI (previously CLI/option-only). wp podcast stats prune [--limit=N]WP-CLI subcommand.- CBR bitrate-mode admin note. When the source MP3 is VBR/ABR, the attachment form shows an amber informational note. FrequencIA does not re-encode audio.
- Importer: channel-mapping preview. The Import admin page lists each detected source’s channels with the planned action (“will create” / “will update term N”) before the operator runs the import.
- Importer: SSP recording date. SSP’s
date_recordedmeta is migrated to_podcast_recorded_date(data preservation only; no editor UI yet). - Importer: Podlove social-service URLs. The optional
podlove_modules_contributors_servicetable is read; the first valid http(s) URL per contributor is stored as_podcast_person_url. - Importer: Podlove voice→person mapping. The optional
podlove_modules_voiceassignmenttable is read (gracefully; no-op when the module is inactive); raw transcript voice labels are resolved to the mapped contributor’s name in the WebVTT output.
Changed
- i18n: all 282 missing strings translated to
es_ESandcafollowing the project style guides (vós/imperative for ca; tú for es; «» quotes;suprimirfor delete;complementfor plugin). .pot regenerated (523 strings), .mo compiled, 8 JS .json regenerated. Native-speaker review still recommended before public release. - Test stub:
WpdbSpy::query()now pops from areturn_querystack (defaults totrue);checked()/selected()/disabled()default$two = true— matching WordPress core. bin/deploy.sh: excludeCHANGELOG.mdfrom the release ZIP (canonical changelog ischangelog.txt; the Keep-a-Changelog-formatCHANGELOG.mdhas drifted since v1.7.0).
Fixed
StatsEndpoint::register()triggered_doing_it_wrongon every admin page load becauseregister_rest_route()ran oninitinstead ofrest_api_init. Now hooksrest_api_initvia a dedicatedregister_routes()callback.uninstall.phpnow cleans up the statistics subsystem per spec §5: cancels 3 stats AS hooks; deletes 4 stats options; removes the GeoIP database; and, on the data-removal opt-in, drops{prefix}podcast_download+_monthlyand the_podcast_downloads_total/7d/30dpostmeta.frequencia_deactivate()now unschedules all three stats AS hooks alongsidepodcast_process_episode.- Settings → Stats retention notice distinguishes “paused” (statistics disabled) from “0 days effective”.
- Importer transcript/chapter idempotency. A standalone re-run of Phase 12.6 now overwrites the existing attachment in place instead of orphaning the old one.
Compatibility
- WordPress: 7.0
- PHP: 8.2 – 8.5
- MariaDB: 11.4+
Tests
- PHPCS: 0 errors, 0 warnings. PHPStan level 9: 0 errors. PHPUnit: 588 tests, 0 failures (1 pre-existing skip). Preflight: 6/6 PASS. AI audit:
docs/audit-pre-deploy-1.9.3.md.
1.9.1
_Release date: 2026-07-17_
Highlights
- Security hardening: resolves all 2 WARNING + 2 INFO findings from the v1.9.0 clean-context audit.
Fixed
ClientIpnow validatesREMOTE_ADDRagainst a filterable trusted-proxy list (frequencia_trusted_proxies, default: localhost) before honouringX-Forwarded-For/CF-Connecting-IP. Prevents header spoofing → dedup manipulation.GeoIpUpdatervalidates the downloaded mmdb end-to-end: opens it with the MaxMind reader and resolves8.8.8.8before installing. Rejects corrupt/tampered files.TrackingEndpoint:sourceparameter whitelist-validated (feed/player/download/embed); unknown values default todownload.Aggregator::upsert_monthly:REPLACE INTOinstead of deprecatedON DUPLICATE KEY UPDATE ... VALUES()(MariaDB 11.4+ future-proofing).
Compatibility
- WordPress: 7.0
- PHP: 8.2 – 8.5
- MariaDB: 11.4+
Tests
- PHPCS: 0 errors, 0 warnings. PHPStan level 9: 0 errors. PHPUnit: 573 tests. Preflight: 6/6 PASS.
1.9.0
_Release date: 2026-07-17_
Highlights
- Statistics module: anonymous download/play counting with GeoIP, client detection, monthly trends, and a REST API.
Added
- Statistics module (5 phases, per
docs/stats-module-spec.md):
– StatsTracker — writes raw download events with hash(salt + IP + UA) de-dup key; bot/HEAD/range filtering.
– StatsAggregator — cursor-based hourly aggregation: deduped per (day, listener-hash); postmeta totals + monthly rollup upsert.
– StatsTrackingEndpoint — rewrite /frequencia/media/{id}/{kind}/ → record hit → 302 redirect. Always registered; records only when opt-in is on.
– StatsGeoIp + GeoIpUpdater — MaxMind DB reader (custom country_code schema); monthly AS download from ip.robotstxt.es with magic-marker validation.
– StatsClientDetector — 17 podcatcher UA patterns.
– AdminStatsPage — at-a-glance, 12-month CSS-bar trend, top episodes/countries/clients. manage_options gated.
– StatsStatsEndpoint — GET /frequencia/v1/stats REST read.
– CliStatsCommand — wp podcast stats seed/aggregate.
– Episode-list “Downloads” column.
– bin/preflight.sh — automated pre-deploy verification (6 sections).
- Database schema v2 —
{prefix}podcast_download(raw events) +{prefix}podcast_download_monthly(rollup).FREQUENCIA_DB_VERSION → 2. - Composer dependency:
maxmind-db/reader ^1.13.
Changed
- Media import: follows HTTP redirects; external files referenced as URL-attachments when download is off; local files reused without copy. Imports the source featured image (
_thumbnail_id).
Compatibility
- WordPress: 7.0
- PHP: 8.2 – 8.5
- MariaDB: 11.4+
Tests
- PHPCS: 0 errors, 0 warnings. PHPStan level 9: 0 errors. PHPCompatibility 8.2–8.5: 0 errors. PHPUnit: 573 tests, 0 failures. Preflight: 6/6 PASS. Security audit performed (
docs/security-audit-1.9.0.md).
1.8.3
_Release date: 2026-07-17_
Highlights
- Importer robustness: recover from a stale source-to-target map after episodes are deleted, and import the source featured image.
Fixed
- Re-importing after the imported episodes were deleted produced an empty episode list. The importer trusted the persistent
IdMapeven when its target post IDs no longer existed (deleted), so it either skipped them (skip_existing) or wrote meta to dead IDs.Importer::import_episodesnow verifies the mapped target post still exists; if not, it imports a fresh post and updates the map.
Added
- Featured image import:
EpisodeRecord.featured_image_idcarries the source_thumbnail_id.Importer::set_episode_metaresolves the cover preferring a valid local attachment (foreign/dangling source IDs are ignored vialocal_attachment_id()), else resolves thecover_imageURL throughMediaResolver, and sets both_podcast_episode_cover_idand the WP featured image (set_post_thumbnail).
Compatibility
- WordPress: 7.0
- PHP: 8.2 – 8.5
- MariaDB: 11.4+
Tests
- PHPCS: 0 errors, 0 warnings. PHPStan level 9: 0 errors. PHPCompatibility 8.2–8.5: 0 errors. PHPUnit: 573 tests, 0 failures (1 pre-existing skip). Dedicated security audit performed (
docs/security-audit-1.8.3.md).
1.8.2
_Release date: 2026-07-17_
Highlights
- Catalog importer fixes: the AJAX run works on WP 7.0, respects Limit/Offset, and resolves media correctly.
Fixed
- AJAX import returned
403 -1on every batch under WordPress 7.0:check_ajax_referer()only inspects$_REQUEST['_ajax_nonce']/_wpnonce, not the barenoncekey the client sends. It is now passed explicitly as the query arg. - AJAX import ignored the form’s Limit/Offset fields (it imported the whole catalog). The first batch now records the start offset + total-episode cap; each batch’s slice is capped by the remaining allowance; the run finishes at
min(total, start_offset + limit).
Changed
MediaResolverfollows HTTP redirects to the final media URL, then: existing local attachment → reuse; local file on disk → reference (no copy); remote file → download when--download-mediais on, else create a URL-only attachment whose guid is the final URL (wp_get_attachment_url()returns it verbatim, so feed/player stream from the origin). Idempotent via a_podcast_source_urlmeta lookup.
Maintenance
- Database schema v2:
{prefix}podcast_download(raw events) and{prefix}podcast_download_monthly(rollup) created for the upcoming statistics module. No tracking code yet — tables are empty and harmless.FREQUENCIA_DB_VERSION → 2.
Compatibility
- WordPress: 7.0
- PHP: 8.2 – 8.5
- MariaDB: 11.4+
Tests
- PHPCS: 0 errors, 0 warnings. PHPStan level 9: 0 errors. PHPCompatibility 8.2–8.5: 0 errors. PHPUnit: 572 tests, 0 failures (1 pre-existing skip).
1.8.1
_Release date: 2026-07-16_
Highlights
- Cleaner episode list: deduplicated columns in a fixed order.
Changed
EpisodeColumns::add_columnsnow returns a fixed column order (No. → Channel / Season → Title → Duration → Type → AI Status → Author → Date) and drops the auto-addedtaxonomy-podcast_channel/taxonomy-podcast_seasoncolumns that duplicated the merged “Channel / Season” column.
Compatibility
- WordPress: 7.0
- PHP: 8.2 – 8.5
Tests
- PHPCS: 0 errors, 0 warnings. PHPStan level 9: 0 errors. PHPUnit: 568 tests, 0 failures (1 pre-existing skip).
1.8.0
_Release date: 2026-07-16_
Highlights
- Live, batched catalog import with a progress bar (no timeouts), plus real-data importer fixes and a fully clean PHPCS/PHPStan pass.
Added
- Batched import over admin-ajax: the admin Import page streams a real run in batches of 15 with a live progress bar and scrolling per-item log, avoiding PHP timeouts on large catalogs. Dry runs still submit synchronously; WP-CLI is unchanged.
Importer::run_batch()imports an episode slice; newimport_transcripts_for()/import_chapters_for()scope transcript and chapter work to the current batch, so the persistent source-to-target IdMap no longer causes duplicate attachments across batches.- Source detection now shows live channel/season/person/episode counts per detected source; a dry run reports the planned counts instead of always-zero.
- Episode number falls back to the leading digits of the post title when the source’s
itunes_episode_numbermeta is empty (common with Seriously Simple Podcasting).
Changed
- Only published (
post_status = publish) episodes are imported/counted; drafts, future and trash are skipped. WordPress.DB.DirectDatabaseQueryscoped off for the importer source readers in.phpcs.xml(they exist to read foreign plugin tables directly; no WP API covers this).
Fixed
- Transcript and chapter attachments were duplicated when an import re-iterated the full persistent IdMap.
Compatibility
- WordPress: 7.0
- PHP: 8.2 – 8.5
- MariaDB: 11.4+
Tests
- PHPCS: 0 errors, 0 warnings. PHPStan level 9: 0 errors. PHPCompatibility 8.2–8.5: 0 errors. PHPUnit: 568 tests, 0 failures (1 pre-existing skip).
1.7.0
_Release date: 2026-07-06_
Highlights
- Numeric global seasons, episode title-prefix format, and a
podcast:updateFrequencyfeed tag.
Added
- Episode title-prefix format —
N.PREFIX - Titlein feed and website (not editor); per-channel prefix (max 64) with global fallback; number applied to full episodes only. - “ — per-channel + global field, emitted in the RSS feed.
Changed
- Season terms are now numeric (name = slug = integer; “Season 3” → “3”); removed the unused
_podcast_season_channel_idmeta. - Merged the Channel and Season admin list columns into one “Channel / Season” column.
Maintenance
- Regenerated the translation template (
.pot, 483 strings); documented the external CBR validator warning.
Compatibility
- WordPress: 7.0
- PHP: 8.2 – 8.5
Tests
- PHPCS: 0 errors. PHPStan level 9: 0 errors. PHPUnit: 570 tests (15 skipped).
1.6.0
_Release date: 2026-07-06_
Highlights
- Catalog importer from Podlove Podcast Publisher and Seriously Simple Podcasting.
Added
- Catalog importer — migrate channels, seasons, persons, episodes, transcripts, and chapters from Podlove or Seriously Simple Podcasting. Idempotent, non-destructive, GUID-preserving; AI pipeline suppressed on import. WP-CLI (
wp podcast import,wp podcast import-status) and an admin Import page.
Compatibility
- WordPress: 7.0
- PHP: 8.2 – 8.5
Tests
- PHPCS: 0 errors. PHPStan level 9: 0 errors.
1.5.0
_Release date: 2026-07-01_
Highlights
- Multi-language subtitle translation and granular per-player placement.
Added
- Subtitle translation: per-channel “Translate subtitles” toggle + “Subtitle languages” multi-select. Whisper returns word-level timestamps; subtitles use short word-grouped cues. The spoken language is auto-detected; the transcript is translated (OpenAI) into each additional selected language, producing one subtitle track per language. The player renders a
per language withsrclang/label. - Granular player placement: independent before/after/none for the audio and video players, plus a “player order” setting (video-first / audio-first) for when both share a slot. Backwards-compatible with the legacy single-player setting.
Changed
WhisperClientrequests bothsegmentandwordgranularities.WebVTTFormatterexposescues()/format_cues(); word-grouped cues with a segment fallback.Playerrenders multiple subtitleelements (was a single hardcodedsrclang="es").
Compatibility
- WordPress: 7.0
- PHP: 8.2 – 8.5
Tests
- PHPCS: 0 errors. PHPStan level 9: 0 errors. PHPCompatibility 8.2–8.5: 0 errors. composer audit: 0 advisories. PHPUnit: 217 unit tests, 0 failures.
1.4.0
_Release date: 2026-07-01_
Highlights
- Correct, flag-based rewrite-rule flushing and iTunes episode-numbering feed compliance.
Added
FlushManager: rewrite rules flush only on activation, episode-slug change, or plugin version change. Covers the WP updater (upgrader_process_complete) and aplugins_loadedversion-compare fallback for manual / Git / rsync deploys.- Optional episode-number title prefix in the RSS feed (Settings → Podcast → Feeds).
Fixed
- “ omitted for trailer/bonus episodes (Apple Podcasts spec).
frequencia_activate()registers the CPT before flushing, so episode permalinks work right after activation._podcast_video_durationcleaned up on uninstall.
Compatibility
- WordPress: 7.0
- PHP: 8.2 – 8.5
Tests
- PHPCS: 0 errors. PHPStan level 9: 0 errors. PHPCompatibility 8.2–8.5: 0 errors. composer audit: 0 advisories. PHPUnit: 214 unit tests, 0 failures.
1.3.0
_Release date: 2026-06-30_
Highlights
- Video duration tracking and video-by-default playback for episodes with both audio and video.
Added
_podcast_video_durationmeta field: the MP4 length is auto-filled (server-side + Block Editor), shown in the editor sidebar, and used in the video RSS feed’s “.
Changed
- Episodes with both an MP3 and an MP4 now show the video player by default (captions + chapters), instead of the audio player.
MediaHooksnow syncs both audio and video durations; the editor sidebar shows separate “Audio duration” and “Video duration” fields.- The video RSS feed prefers the video duration for “.
Compatibility
- WordPress: 7.0
- PHP: 8.2 – 8.5
Tests
- PHPCS: 0 errors. PHPStan level 9: 0 errors. PHPCompatibility 8.2–8.5: 0 errors. composer audit: 0 advisories. PHPUnit: 206 unit tests, 0 failures.
1.2.0
_Release date: 2026-06-29_
Highlights
- Quick Add Episode: a one-screen creation flow that runs the full AI pipeline automatically and tracks progress live.
Added
- Quick Add Episode screen (FrequencIA → Quick Add): pick MP3 (required), optional MP4, channel, and season; creates a draft titled “Episode N”, auto-queues the AI pipeline, and shows an inline progress stepper (Created → Queued → Transcribing → Summarizing → Ready for review) that polls until review, then links to the editor.
- Episode number auto-increment: new episodes get the next sequential number (highest existing + 1) for Block Editor, classic, and programmatic saves.
- Duration auto-fill in the Block Editor: selecting an audio file populates the duration immediately from attachment metadata.
- Timestamped transcript: Phase A stores [HH:MM:SS]-prefixed segments so the LLM anchors chapter start times to the real audio.
- REST endpoint
GET /frequencia/v1/episode/{id}/status(status, activity log, edit URL, error).
Changed
- “Quick Add” is the first submenu under the FrequencIA menu.
package.jsonversion kept in sync with the plugin header.
Fixed
- Settings page “Select image” button did nothing (media uploader never enqueued; inline JS checked
wp.mediatoo early). - Chapter timestamps did not match the audio:
ChaptersFormatternow acceptsMM:SS, and the LLM is fed real Whisper segment timestamps. - Episode number field was always empty (auto-increment was never implemented).
- Duration field stayed empty after attaching audio (server-side auto-fill overwritten by the REST meta save).
- Test suite drift: missing
sanitize_titlestub, stale meta field count, version stub mismatch, test-isolation bug skipping 3 tests. readme.txtchangelog was missing the 1.1.0 entry.
Security
- Security audit passed (OWASP/WordPress hardening). Risk: Low.
- Quick Add form: nonce +
edit_postscapability check; REST status route gated byedit_postpermission callback. - No sensitive data (API keys, paths) exposed via the new REST endpoint.
Compatibility
- WordPress: 7.0
- PHP: 8.2 – 8.5
- MariaDB: 11.4+
Tests
- PHPCS: 0 errors (WordPress + WordPress-Docs + WordPress-Extra + PHPCompatibilityWP).
- PHPStan: level 9, 0 errors.
- PHPUnit: 219 tests, 0 failures (14 integration tests skip without WP_TESTS_DIR).
- PHPCompatibility scan: 8.2–8.5, 0 errors.
- composer audit: 0 advisories.
1.1.0
_Release date: 2026-06-25_
Added
- Block Editor sidebar panels for all episode metadata and a People panel with roles.
- AI Status panel: processing event log, stuck detection, re-queue via REST API.
- AI Content panel persists after publication: transcript download, editable summary/chapters.
- REST endpoints: requeue / approve / discard / regen / save-ai-content.
- Regenerate summary and title via background Action Scheduler job.
- Spanish (es_ES) and Catalan (ca) translations including Block Editor JS JSON.
Fixed
- Block Editor iframe buttons converted to fetch() REST calls.
- Summary copied to post_content on first approval.
- Chapters startTime conversion; duration MIME detection broadened.
- Action Scheduler bootstrap; episode number defaulting; feed URLs with plain permalinks.
Compatibility
- WordPress: 7.0
- PHP: 8.2 – 8.5
1.0.0
_Release date: 2026-06-24_
Highlights
- Initial stable release: full AI podcast pipeline, multi-standard RSS, HTML5 player, Gutenberg blocks.
Added
- Full AI pipeline: transcription (Whisper), summarization and chapters (GPT), editorial review.
- Multi-standard RSS feeds (RSS 2.0, iTunes, Podcasting 2.0) per channel.
- HTML5 player with speed/skip/chapters/WebVTT; episode-player, episode-list, subscribe blocks.
- WP 7.0 Connectors API integration; async processing queue with retries.
- WP-CLI commands: process, status, reprocess-all, flush-cache.
- Rate limiting; complete uninstall.php.
Compatibility
- WordPress: 7.0
- PHP: 8.2 – 8.5
0.2.0
_Release date: 2026-06-23_
- Phase 1: CPTs, taxonomies, meta fields, DB schema, PHP 8.2 enums.
0.1.0
_Release date: 2026-06-23_
- Phase 0: plugin scaffolding and development tooling.