Supply a transcript URL from your own service
Core’s Podcasting 2.0 auto-detection scans an episode’s attached media for a single .vtt, .srt or .txt file and writes the one it finds to the Transcript URL field. This filter is the seam for everything else — a transcription service, an S3 bucket, a naming convention on your own CDN.
It runs only when the Transcript URL field is empty, so a URL you return can never overwrite one the podcaster typed — you don’t need to check that yourself.
$url is core’s detected URL, or null when core found nothing usable — either no transcript-shaped attachment, or more than one, which core deliberately refuses to guess between. You cannot tell those two apart from here; if you need to, read the attachments yourself.
Returning a non-empty string also suppresses the “several transcript files are attached” admin notice, because the field no longer needs a human to fill it. Return null (or '') to leave the field alone — that is how you switch core detection off.
The stored type is inferred from the URL’s extension (.vtt → text/vtt, .srt → application/srt, .json → application/json, .txt → text/plain, .html → text/html). An extension not in that list leaves the stored type untouched rather than forcing a wrong one — so a URL with no extension, or one behind a signing endpoint, keeps whatever the podcaster chose in the dropdown.
It fires inside EpisodeMetaSaver::save(), which every save path routes through, so one callback covers the React editor’s REST save, the classic editor and your own save() calls. ⚠ It does not fire on a save that never reaches the saver — a bare wp_update_post() with no Benecaster meta in play writes nothing and detects nothing.
To disable core detection entirely — for instance because your own admin screen owns the field:
add_filter( 'benecaster_podcast2_transcript_autodetect', '__return_null', 99 );
Code
<?php
add_filter(
'benecaster_podcast2_transcript_autodetect',
function ( ?string $url, int $episode_id ): ?string {
// Let core's media-library detection win when it found something.
if ( null !== $url ) {
return $url;
}
$external_id = get_post_meta( $episode_id, '_my_service_transcript_id', true );
if ( '' === $external_id ) {
return null; // Nothing to offer — leave the field empty.
}
// Keep the extension: it is what sets the transcript type.
return 'https://transcripts.example.com/' . rawurlencode( (string) $external_id ) . '.vtt';
},
10,
2
);
Hooks Used
Need this built rather than just documented? See our services →