No description
Find a file
2026-06-04 15:39:13 +02:00
extensions Initial fresh import 2026-06-04 15:28:29 +02:00
.gitignore Initial fresh import 2026-06-04 15:28:29 +02:00
CHANGELOG.md Initial fresh import 2026-06-04 15:28:29 +02:00
LICENSE Initial fresh import 2026-06-04 15:28:29 +02:00
package-lock.json Initial fresh import 2026-06-04 15:28:29 +02:00
package.json Update package metadata 2026-06-04 15:39:13 +02:00
README.md Initial fresh import 2026-06-04 15:28:29 +02:00
tsconfig.json Initial fresh import 2026-06-04 15:28:29 +02:00

pi-codex-transcribe

Experimental Pi extension for transcribing local audio files through ChatGPT/Codex using Pi's existing openai-codex login.

This package does not use OPENAI_API_KEY and does not call the public OpenAI API.

On Windows/macOS/Linux it uses Node fetch first, then automatically falls back to the local curl executable if ChatGPT returns a Cloudflare challenge. Install curl if it is not already on your PATH.

Install / local test

From this repository:

pi install /path/to/Pi-Extensions/PI-Codex-Transcribe

For a one-off test without installing:

pi -e /path/to/Pi-Extensions/PI-Codex-Transcribe

Authentication

The tool uses Pi's existing openai-codex provider credentials:

/login

Select ChatGPT Plus/Pro (Codex) and complete the login flow. The extension reads the token with:

ctx.modelRegistry.getApiKeyForProvider("openai-codex")

It also extracts chatgpt_account_id from the token and sends it as ChatGPT-Account-ID.

Usage that avoids context-length failures

Use the slash command for audio files. It bypasses the LLM/tool-selection step, so Pi will not try to read or attach the MP3 into model context. The full transcript is saved to ~/.pi/agent/pi-codex-transcribe/transcripts/ and only a small preview is shown in chat:

/codex-transcribe dialogo.mp3

The command also strips a leading @, so this is safe too:

/codex-transcribe @dialogo.mp3

Optional debugging flags:

/codex-transcribe dialogo.mp3 --field audio --mime audio/mpeg

The extension also intercepts simple natural-language transcription requests like:

Me puedes pasar esto a texto: @dialogo.mp3

and handles them directly before the model sees the audio path. Large transcripts and error bodies are truncated in chat to avoid filling the context window.

Tool

Also registers one LLM-callable tool:

codex_transcribe_audio

Parameters:

Parameter Type Required Description
audioPath string yes Local audio file path. Relative paths resolve under the current workspace.
language string no Optional language hint form field, e.g. en.
prompt string no Optional transcription prompt/context form field.
fieldName string no Multipart field-name override. Defaults to file; useful for testing audio or audio_file.
mimeType string no MIME type override. Defaults to extension-based detection.

Supported extension defaults:

Extension MIME type
.webm audio/webm
.wav audio/wav
.mp3 audio/mpeg
.m4a audio/mp4
.mp4 audio/mp4
other application/octet-stream

How it works

  1. Reads the local audio file.
  2. Resolves the openai-codex token from Pi.
  3. Extracts chatgpt_account_id from the JWT.
  4. Sends a multipart/form-data POST request to:
https://chatgpt.com/backend-api/transcribe

Required headers use the Codex CLI-style fingerprint:

Authorization: Bearer <token>
ChatGPT-Account-ID: <accountId>
originator: codex_cli_rs
User-Agent: codex_cli_rs/...
OpenAI-Beta: responses=experimental
session-id: <uuid>
x-client-request-id: <uuid>

If Node fetch is challenged by Cloudflare, the extension retries with curl using the same headers and a tiny in-memory allowlist of Cloudflare infrastructure cookies only. The token is never logged or returned. Successful transcriptions are written to:

~/.pi/agent/pi-codex-transcribe/transcripts/<timestamp>-<audio-name>.txt

Only a preview is returned to Pi chat, so long audio does not fill the model context.

Experimental status and risks

This depends on a private ChatGPT/Codex backend endpoint. It may break without notice, vary across accounts/regions/clients, or be blocked by browser/session checks such as Cloudflare. It is not the official OpenAI API.

TTS is not included here and is not confirmed through Codex subscription auth.

Troubleshooting

If you previously got context_length_exceeded, update/reload this package, then start a fresh session with /new. Old sessions may already contain the huge audio/text payload.

Use /codex-transcribe dialogo.mp3 instead of asking the model to call the tool. The command runs inside the extension directly and prevents Pi from attaching the audio file to the model context.

On non-2xx responses, the tool/command error includes status code, a truncated response body preview, content type, sanitized response headers, form field name, MIME type, file name, and audio byte count.

Status Likely cause What to try
401 Missing/expired Codex token Run /login again and select ChatGPT Plus/Pro (Codex).
403 Account/session rejected or shared entitlement issue Re-login; verify the account has Codex/ChatGPT access; check for browser/session enforcement.
415 Unsupported media type Try .webm; override mimeType to audio/webm, audio/wav, or audio/mpeg.
422 Multipart shape rejected Try fieldName: "audio" or fieldName: "audio_file"; check whether language/prompt fields should be omitted.
Cloudflare/HTML body Node fetch blocked The extension should auto-fallback to curl. Check that curl --version works. Curl fallback is always enabled in this development version.

Start with a small .webm file because browser-style recording is the most likely shape expected by the endpoint.