Audio & Video

Audio Transcription

⏱ 14 min

Stated as directly as possible: the WordPress PHP AI Client SDK does not offer audio transcription today. There is no transcribe(), no generate_transcript_result(), no method of any name for turning an audio file into text anywhere in the SDK’s public API. Audio appears in the SDK as an output modality, generating speech from text is a real, confirmed capability, and as an input modality for models that can reason about audio content in a broader sense. But speech-to-text transcription specifically isn’t exposed as a capability the SDK’s CapabilityEnum or builder methods currently name. If a project needs transcription today, the real path is calling a provider’s transcription API directly over HTTP, outside wp_ai_client_prompt() entirely, using that provider’s own API key and endpoint. This lesson shows that real path.

What you'll learn in this lesson
Why this isn't a WP AI Client SDK call
Confirming there is no transcription method in the SDK today, and what that means practically.
Calling a provider's transcription endpoint directly
Using wp_remote_post() with the provider's own API key, separate from your WP AI Client provider configuration.
Handling the file upload correctly
Sending audio as multipart form data, since transcription endpoints typically don't accept JSON bodies with embedded audio.
Storing the transcript
Saving the result as post meta so later lessons in this course can summarize it.
Prerequisites

Course 5’s lesson on managing API keys across providers gives useful background on credential storage, even though this lesson’s credential is for a service outside the WP AI Client’s own provider system entirely.

This lesson is a real workaround, not a WP AI Client feature

Nothing in this lesson calls wp_ai_client_prompt() or any other WP AI Client SDK method. That’s deliberate: transcription isn’t something the SDK does yet, so the honest answer is a plain HTTP call to a transcription provider’s own API, managed entirely outside the SDK’s provider abstraction. If the SDK adds transcription support later, that would be the better path going forward, check its repository before assuming this lesson’s approach is still the recommended one.

Step 1: Why you can’t reach for wp_ai_client_prompt() here

Every builder method covered so far, generate_text(), AiClient::input()->generateEmbedding(), generate_image_result(), maps to a capability documented in the SDK’s own CapabilityEnum: text generation, image generation, embedding generation, speech generation, text-to-speech conversion, video generation, music generation. Speech-to-text transcription isn’t one of the listed capabilities. Calling generate_text() with an audio file attached might work for some broader “listen to this and answer a question about it” use case on a model that supports audio input, but that’s a different job from producing an accurate, complete, word-for-word transcript, and it isn’t a confirmed, purpose-built path either. For an actual transcript, go directly to a provider’s transcription API.

Step 2: Store the provider credential separately

Because this call bypasses the WP AI Client SDK’s provider configuration entirely, it needs its own credential, stored separately from whatever keys Course 5 had you put into the AI Client’s own settings:

// File: my-plugin/class-audio-transcription.php
function my_plugin_get_transcription_api_key(): string {
	$key = defined( 'MY_PLUGIN_TRANSCRIPTION_API_KEY' ) ? MY_PLUGIN_TRANSCRIPTION_API_KEY : '';

	if ( ! $key ) {
		$key = get_option( 'my_plugin_transcription_api_key', '' );
	}

	return $key;
}

Same pattern Course 5 recommended for AI Client provider keys, a constant in wp-config.php first, an option as a fallback for a settings-screen-based setup. The point is that this key belongs to a transcription provider’s account, not to whichever provider you configured for text and image generation, they may or may not be the same company, and even when they are, the API keys are typically not interchangeable between their different product APIs.

Step 3: Sending the audio file over HTTP

Transcription endpoints generally expect the audio uploaded as multipart form data, not embedded as base64 inside a JSON body the way File objects work elsewhere in this course. WordPress’s HTTP API supports multipart bodies directly:

// File: my-plugin/class-audio-transcription.php
function my_plugin_transcribe_audio( string $file_path ): string|WP_Error {
	$api_key = my_plugin_get_transcription_api_key();

	if ( ! $api_key ) {
		return new WP_Error( 'missing_api_key', 'No transcription API key configured.' );
	}

	$boundary = wp_generate_password( 24, false );
	$file_data = file_get_contents( $file_path ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents

	if ( false === $file_data ) {
		return new WP_Error( 'unreadable_file', 'Could not read the audio file.' );
	}

	$body  = "--{$boundary}\r\n";
	$body .= 'Content-Disposition: form-data; name="file"; filename="' . basename( $file_path ) . "\"\r\n";
	$body .= "Content-Type: audio/mpeg\r\n\r\n";
	$body .= $file_data . "\r\n";
	$body .= "--{$boundary}\r\n";
	$body .= "Content-Disposition: form-data; name=\"model\"\r\n\r\n";
	$body .= "your-provider-transcription-model\r\n";
	$body .= "--{$boundary}--\r\n";

	$response = wp_remote_post(
		'https://api.your-transcription-provider.example/v1/audio/transcriptions',
		array(
			'timeout' => 120,
			'headers' => array(
				'Authorization' => 'Bearer ' . $api_key,
				'Content-Type'  => 'multipart/form-data; boundary=' . $boundary,
			),
			'body'    => $body,
		)
	);

	if ( is_wp_error( $response ) ) {
		return $response;
	}

	$code = wp_remote_retrieve_response_code( $response );
	$data = json_decode( wp_remote_retrieve_body( $response ), true );

	if ( 200 !== $code || ! is_array( $data ) || empty( $data['text'] ) ) {
		return new WP_Error( 'transcription_failed', 'Transcription request did not return usable text.' );
	}

	return $data['text'];
}
The endpoint URL and body shape here are illustrative

The exact endpoint path, required form fields, and response shape differ by transcription provider, this code shows the general multipart pattern, not a specific provider’s documented contract. Before shipping this, check your chosen provider’s own current API reference for the real endpoint, required parameters, accepted audio formats, and file size limits, and adjust accordingly.

Step 4: A longer timeout, deliberately

Notice the 'timeout' => 120 above. Transcription of anything beyond a short clip takes meaningfully longer than a typical text generation call, WordPress’s HTTP API default timeout is far too short for a multi-minute audio file. Raise it explicitly rather than letting a real transcription job time out partway through.

Step 5: Storing the transcript

// File: my-plugin/class-audio-transcription.php
$transcript = my_plugin_transcribe_audio( $file_path );

if ( ! is_wp_error( $transcript ) ) {
	update_post_meta( $attachment_id, '_my_plugin_transcript', wp_kses_post( $transcript ) );
}

Storing the transcript as post meta on the audio attachment keeps it attached to the file it belongs to, and sets up the next lesson, which summarizes a transcript like this one with generate_text(), a step that’s back on solid, confirmed SDK ground.

Test it: transcribe a short real audio file

wp-env run cli wp eval '
$result = my_plugin_transcribe_audio( "/path/to/a/short-test-clip.mp3" );
if ( is_wp_error( $result ) ) {
	echo "Error: " . $result->get_error_message() . "\n";
} else {
	echo "Transcript: " . $result . "\n";
}
'

You should see either real transcribed text matching what’s actually said in the clip, or a clear WP_Error message, not a silent failure.

Don't confuse this key with your AI Client provider key

It’s easy to reuse the same API key you configured for wp_ai_client_prompt() here and have it fail confusingly, or worse, silently hit a different product’s usage limits on the same account. Keep the transcription credential explicitly separate in your settings UI and your code, with its own label, so nobody configuring this plugin later assumes one key covers both.

Recap

There is no transcription method in the WordPress PHP AI Client SDK today, that’s a real gap, not an oversight in this course. The honest, working path is a direct HTTP call to a transcription provider’s own API using wp_remote_post(), multipart form data for the audio file, that provider’s own API key stored separately from your AI Client provider configuration, and a raised timeout to accommodate longer clips. Store the resulting transcript as post meta, since the next lesson picks it up from there.

Resources & further reading

← Vision: Analyzing Images for Alt Text and Tagging Generating Video Summaries From Transcripts →