Skip to main content

benecaster_podcast2_transcript_autodetect

Filter Free

Fills an episode’s Podcasting 2.0 Transcript URL from somewhere other than the media library. Core’s own auto-detection scans the episode’s attached media for a single .vtt, .srt or .txt file and writes the one it finds; this filter is the seam for everything else — a transcription service, an S3 bucket, a naming convention on your own CDN.

Runs on every episode save, but 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 arrives as core’s own detected URL, or null when core found nothing usable: no transcript-shaped attachment, or more than one, which core deliberately refuses to guess between. You can’t tell those two cases apart from here; read the attachments yourself if you need to.

Returning a non-empty string also suppresses the “several transcript files are attached” admin notice, since the field no longer needs a human to fill it in. Return null (or '') to leave the field alone — that’s how you switch core detection off entirely.

The stored MIME type is then inferred from the returned URL’s extension (.vtttext/vtt, .srtapplication/srt, .jsonapplication/json, .txttext/plain, .htmltext/html). An extension not in that list leaves the stored type untouched rather than forcing a wrong one.

Fires from Benecaster\Episode\TranscriptAutodetector, called at the end of EpisodeMetaSaver::save() — every save path routes through there, 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.

Supply a transcript URL from your own service

Free Intermediate

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 (.vtttext/vtt, .srtapplication/srt, .jsonapplication/json, .txttext/plain, .htmltext/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 );
<?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
);

View on GitHub →

Parameters

Name Type Default Description
$url ?string Core's detected transcript URL, or null when core found nothing usable.
$episode_id int ID of the episode being saved.

Returns: ?string

Examples

Supply a transcript URL from your own service

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
);

Disable core detection entirely

add_filter( 'benecaster_podcast2_transcript_autodetect', '__return_null', 99 );

Need this built rather than just documented? See our services →