A Python script for uploading caption/transcript files to PeerTube videos, driven by a Google Sheet that maps video metadata to caption files.
This script reads a Google Sheet containing video records, looks up each video on a PeerTube instance by its short UUID, and uploads an associated caption file (.srt or .vtt) via the PeerTube API. It supports dry-run mode, flexible configuration via a YAML file, and command-line overrides for most settings.
Python 3.10+ (uses dict | None union syntax)
Install dependencies:
pip install \
pyyaml \
pandas \
requests \
urllib3 \
langcodes \
google-auth \
google-api-python-client \
openpyxlThe script requires a YAML configuration file. Below is the expected structure:
log_file: /path/to/logfile.log
google_credentials_file: /path/to/google-service-account.json
google_sheet_id: "your_google_sheet_id"
google_sheet_name: "Sheet1"
id_column: id
environments:
production:
peertube_instance: https://your-peertube-instance.example.com
peertube_username: admin
peertube_password: yourpassword
peertube_channel: 1
staging:
peertube_instance: https://staging.example.com
peertube_username: admin
peertube_password: stagingpassword
peertube_channel: 2Multiple environments can be defined under environments:. The --env argument selects which one to use at runtime.
id_column sets the name of the column in the Google Sheet used as the unique identifier for each video record. Defaults to id if omitted. Can be overridden at runtime with --id-column.
The script reads from a Google Sheet with the following columns:
| Column | Required | Description |
|---|---|---|
(configurable, default id) |
Yes | A local identifier for the video record. Column name is set via id_column in the config file or --id-column on the command line. |
title |
Yes | Title of the video |
file |
Yes | Path to the local video/media file |
field_media_oembed_video |
Yes | Full URL to the PeerTube video (used to extract the short UUID) |
transcript |
No | Path to the caption file (.srt or .vtt) |
transcript_language |
No | Language name or code for the caption (e.g. English, en, fra) |
If transcript_language is omitted or blank, it defaults to zxx (no linguistic content).
python upload-media-transcripts.py \
--config-file config.yaml \
--log-file run.log \
--env production| Argument | Required | Description |
|---|---|---|
--config-file |
Yes | Path to the YAML configuration file |
--log-file |
Yes | Path to the log output file |
--env |
Yes | Environment key from the config file (e.g. production) |
--dry-run |
No | True or False (default: False). Skips actual API uploads |
--in-google-sheet-id |
No | Override the Google Sheet ID from config |
--in-google-sheet-name |
No | Override the sheet tab name from config |
--in-google-creds-file |
No | Override the Google credentials file from config |
--peertube-instance |
No | Override the PeerTube instance URL |
--peertube-username |
No | Override the PeerTube username |
--peertube-password |
No | Override the PeerTube password |
--peertube-channel |
No | Override the PeerTube channel number |
--id-column |
No | Override the name of the identifier column from config (default: id) |
Validates configuration and logs what would be uploaded without making any API calls:
python upload-media-transcripts.py \
--config-file config.yaml \
--log-file dry-run.log \
--env staging \
--dry-run True- Login — Authenticates with the PeerTube instance using OAuth2 and retrieves a bearer token.
- Read Sheet — Reads the Google Sheet into a DataFrame using a service account.
- Process Rows — For each row:
- Extracts the PeerTube short UUID from the
field_media_oembed_videoURL. - Resolves the transcript language to a PeerTube-recognized language code via the
/api/v1/videos/languagesendpoint. - Uploads the caption file using a
PUTrequest to/api/v1/videos/{uuid}/captions/{language}.
- Extracts the PeerTube short UUID from the
- Log Results — Each upload result (success or error) is logged to the log file and printed to stdout.
| Status | Meaning |
|---|---|
204 |
Caption uploaded successfully (expected success response) |
200 |
Caption accepted with a JSON body (non-standard success) |
400 |
Bad request — likely invalid language code or file format |
404 |
Video UUID or language not found on the instance |
The script authenticates with Google Sheets using a service account JSON key file.
- Create a service account in the Google Cloud Console.
- Grant it the Editor role on the target Google Sheet (share the sheet with the service account's email).
- Download the JSON key file and reference it in your config or via
--in-google-creds-file.
All activity is written to the log file specified by --log-file. The log format is:
YYYYMMDD HH:MM:SS.mmm LEVEL message
Errors are also printed to stdout for visibility during interactive runs.
- SSL verification is disabled for PeerTube requests (
verify=False). This suppresses certificate warnings for self-hosted instances with self-signed certificates. For production deployments with valid certificates, you may want to re-enable verification. - Language matching supports both ISO codes (e.g.
en,fra) and full language names (e.g.English,French), resolved against the live PeerTube languages API. The result is cached for the duration of the run. - The script calls
exit()on unrecoverable errors (missing required columns, failed login) but logs and continues on per-row caption upload failures.