Back to confirmed, solid ground after the previous lesson’s honest workaround. There is
no dedicated “watch this video and summarize it” method in the WordPress AI Client SDK,
and this lesson doesn’t need one: a video’s transcript, whether it came from the
previous lesson’s direct provider call or from a caption file that already exists (a
.vtt or .srt file uploaded alongside the video, which many editors already have from
their video hosting workflow), is just text. Summarizing text is exactly what
generate_text() does, and it’s been confirmed and covered in depth since Course 5.
This lesson applies it specifically to transcripts and caption files, and produces a
summary worth actually storing and searching against.
Course 5’s text generation lessons, in particular the generate_text() builder chain
and how to pass a longer block of text as the prompt input. The previous lesson in this
course if you’re working from a freshly transcribed audio track rather than an existing
caption file.
Step 1: Getting plain text out of a caption file
Caption files carry more than just words, cue numbers, timestamps, and formatting markup that would confuse a summarization prompt if passed through unmodified. A simple strip works for both common formats:
// File: my-plugin/class-video-summary.php
function my_plugin_extract_caption_text( string $file_path ): string {
$contents = file_get_contents( $file_path ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents
if ( false === $contents ) {
return '';
}
$lines = explode( "\n", $contents );
$text_lines = array();
foreach ( $lines as $line ) {
$line = trim( $line );
// Skip blank lines, WEBVTT headers, cue numbers, and timestamp lines.
if (
'' === $line
|| 'WEBVTT' === $line
|| preg_match( '/^\d+$/', $line )
|| preg_match( '/-->/', $line )
) {
continue;
}
$text_lines[] = $line;
}
return implode( ' ', $text_lines );
}
This handles the common structure of both .vtt and .srt files well enough for
summarization purposes, it doesn’t need to be a fully correct parser of either format,
just needs to strip out the parts that aren’t spoken words.
Step 2: Summarizing with generate_text()
With plain text in hand, summarizing it is the same generate_text() call covered in
Course 5, shaped with a prompt specific to the job:
// File: my-plugin/class-video-summary.php
function my_plugin_summarize_transcript( string $transcript ): string {
return wp_ai_client_prompt(
"Summarize the following video transcript in 3 to 5 sentences, written for " .
"someone deciding whether to watch the full video. Focus on what the video " .
"covers, not how it's structured. Transcript follows:\n\n" . $transcript
)->generate_text();
}
Being specific about the summary’s purpose, “deciding whether to watch,” steers the model away from a generic play-by-play recap and toward something actually useful as a substitute preview. Adjust the instruction for your own use case: a summary meant for an internal training-video index reads differently than one meant as public-facing marketing copy.
A short video’s transcript fits comfortably within a single prompt. A multi-hour recording’s transcript might not, depending on the model’s context window. If you’re regularly summarizing long-form content, split the transcript into chunks, summarize each chunk, then summarize the summaries, the same divide-and-conquer approach used for any long-document summarization task, not something specific to video.
Step 3: Storing the summary
A generated summary is metadata about the video, not the video’s own content, post meta on the attachment (or on a post that embeds the video) is the natural place for it:
// File: my-plugin/class-video-summary.php
function my_plugin_save_video_summary( int $attachment_id, string $summary ): void {
update_post_meta( $attachment_id, '_my_plugin_video_summary', wp_kses_post( $summary ) );
}
Storing it as meta rather than appending it into post_content keeps it out of the
way of the actual post editing experience, while still making it available anywhere
you query the attachment, in an admin list table column, a REST API response, or a
front-end video player’s description area.
Step 4: Making the summary genuinely searchable
A summary sitting in post meta is already searchable by keyword through a meta_query.
For search that understands meaning rather than exact words, “find videos about
budgeting” matching a summary that never uses the word “budgeting,” embed the summary
the same way Course 10 does for full posts:
// File: my-plugin/class-video-summary.php
use WordPress\AiClient\AiClient;
$values = AiClient::input( $summary )->generateEmbedding()->getValues();
update_post_meta( $attachment_id, '_my_plugin_video_summary_embedding', wp_json_encode( $values ) );
This is the same AiClient::input()->generateEmbedding() method covered in Course 5’s
embeddings lesson, a separate class from the wp_ai_client_prompt() used for the
summary text itself, applied here to a video summary instead of a post body. If building real
semantic search on top of stored embeddings like this is new territory, Course 10:
RAG & Knowledge Bases in WordPress covers
embeddings and retrieval in full depth, this lesson only needs the single call above to
make a video summary a candidate for that kind of search.
Test it: summarize a real caption file
wp-env run cli wp eval '
$text = my_plugin_extract_caption_text( "/path/to/a/real-captions.vtt" );
$summary = my_plugin_summarize_transcript( $text );
echo $summary . "\n";
'
You should see a short, coherent summary that reflects the actual content of that specific caption file, not a generic placeholder paragraph.
Auto-generated captions on some hosting platforms are wrong often enough to matter, mangled names, dropped words, or entire sections of silence rendered as garbled text. A summary built on a bad transcript will be confidently wrong in the same places the transcript was, worth a quick human skim of the summary before publishing it anywhere a reader would trust it as accurate.
Recap
A video transcript, however you got it, from a direct provider call in the previous
lesson or from an existing caption file, is just text once you’ve stripped out
timestamps and cue markup. Summarizing it is an ordinary generate_text() call with a
prompt aimed at “should I watch this,” and storing the result as post meta keeps it
available for display and, with one more AiClient::input()->generateEmbedding() call,
for real semantic search covered in full in Course 10.
Resources & further reading
- PHP AI Client SDK repository, GitHub
- Introducing the AI Client in WordPress 7.0, make.wordpress.org
- get_post_meta() function reference, developer.wordpress.org