Skip to main content

PGSRip

Rip your PGS subtitles.

Latest Version

License

PGSRip is a command line tool that allows you to extract and convert PGS subtitles into SRT format. This tool requires MKVToolNix and tesseract-ocr and tessdata (https://github.com/tesseract-ocr/tessdata or https://github.com/tesseract-ocr/tessdata_best)

Installation

pgsrip:

$ pip install pgsrip

MKVToolNix:

[Linux/WSL - Ubuntu/Debian]
$ sudo apt-get install mkvtoolnix

[Windows/Chocolatey]
$ choco install mkvtoolnix

tesseract:

PPA is used to install latest tesseract 5.x. Skip PPA repository if you decide to stick with latest official Debian/Ubuntu package

[Linux/WSL - Ubuntu/Debian]
$ sudo add-apt-repository ppa:alex-p/tesseract-ocr5
$ sudo apt update
$ sudo apt-get install tesseract-ocr

[Windows/Chocolatey]
$ choco install tesseract-ocr

tessdata:

Nothing to do: pgsrip downloads the language data it needs on the first rip and reuses it afterwards. See Tesseract language data.

To install every language upfront instead:

$ git clone https://github.com/tesseract-ocr/tessdata_best.git
export TESSDATA_PREFIX=~/tessdata_best

If you prefer to build the docker image Build Docker:

$ git clone https://github.com/ratoaq2/pgsrip.git
cd pgsrip
docker build . -t pgsrip

Tesseract language data

Each subtitle language needs its own tesseract .traineddata file. pgsrip looks for the languages of the subtitles it collected and downloads the ones tesseract does not have yet, before it starts to rip:

$ pgsrip mymedia.mks
1 PGS subtitle collected from 1 file
Downloading tesseract data for por...
Ripping subtitles  [####################################]  100%  mymedia.mks [3:pt-BR]
1 PGS subtitle ripped from 1 file

The data is downloaded only once and is used by every later rip. It is stored in the first writable directory of:

  • --tessdata-dir or the PGSRIP_TESSDATA_DIR environment variable
  • the TESSDATA_PREFIX environment variable
  • %LOCALAPPDATA%\pgsrip\tessdata (Windows), ~/Library/Caches/pgsrip/tessdata (macOS) or ~/.cache/pgsrip/tessdata (Linux)

Languages that tesseract already has are never downloaded, and a subtitle is always ripped with the data that tesseract finds first. To turn the download off and use only the installed languages, use --no-tessdata-download.

Data comes from https://github.com/tesseract-ocr/tessdata_best. Use --tessdata-repository fast (or PGSRIP_TESSDATA_REPO=fast) for the smaller and quicker models of https://github.com/tesseract-ocr/tessdata_fast, or set PGSRIP_TESSDATA_URL to the base URL of a mirror.

Usage

CLI

Rip from a .mkv:

$ pgsrip mymedia.mkv
3 PGS subtitles collected from 1 file
Ripping subtitles  [####################################]  100%  mymedia.mkv [5:de]
3 PGS subtitles ripped from 1 file

Rip from a .mks:

$ pgsrip mymedia.mks
3 PGS subtitles collected from 1 file
Ripping subtitles  [####################################]  100%  mymedia.mks [3:pt-BR]
3 PGS subtitles ripped from 1 file

Rip from a .sup:

$ pgsrip mymedia.en.sup
1 PGS subtitle collected from 1 file
Ripping subtitles  [####################################]  100%  mymedia.en.sup
1 PGS subtitle ripped from 1 file

Rip from a folder path:

$ pgsrip -l en -l pt-BR ~/medias/
11 PGS subtitles collected from 9 files / 2 files filtered out
Ripping subtitles  [####################################]  100%  ~/medias/mymedia.mkv [4:en]
11 PGS subtitles ripped from 9 files

When a path is not ripped, pgsrip prints the reason:

$ pgsrip -l fr ~/medias/
~/medias/mymedia.mkv ignored: mkvmerge not found, install MKVToolNix and make sure that it is in the PATH
0 PGS subtitle collected from 0 file / 1 path ignored

Use -vvv to also see the files that the --language and --age filters removed.

Using docker:

$ docker run -it --rm -v /medias:/medias -u $(id -u username):$(id -g username) ratoaq2/pgsrip -l en -l de -l pt-BR -l pt /medias
11 PGS subtitles collected from 9 files / 2 files filtered out
Ripping subtitles  [####################################]  100%  /medias/mymedia.mkv [4:en]
11 PGS subtitles ripped from 9 files

API

from pgsrip import pgsrip, Mkv, Options
from babelfish import Language

media = Mkv('/subtitle/path/mymedia.mkv')
options = Options(languages={Language('eng')}, overwrite=True, one_per_lang=False)
pgsrip.rip(media, options)

Reporting a bug

A good bug report holds three things: the output of pgsrip doctor, the debug log, and a scrubbed subtitle sample. The bug report form asks for each of them.

When a subtitle cannot be ripped, pgsrip prints the error and the commands that collect what a bug report needs:

$ pgsrip mymedia.mkv
1 PGS subtitle collected from 1 file
0 PGS subtitle ripped from 1 file

1 PGS subtitle could not be ripped:
  mymedia.en.mkv: <ValueError> [max() iterable argument is empty]
To report this, run:
  pgsrip scrub mymedia.mkv
  pgsrip --log-file pgsrip.log mymedia.mkv
The scrubbed subtitle holds no image, only what is needed to reproduce the error.
Attach it to a new issue: https://github.com/ratoaq2/pgsrip/issues

Environment

pgsrip doctor shows what is installed. Add its output to the bug report:

$ pgsrip doctor
pgsrip                       0.1.13
python                       3.13.1 (/usr/bin/python3)
platform                     Linux-6.8.0-generic-x86_64
mkvmerge                     mkvmerge v90.0 (/usr/bin/mkvmerge)
mkvextract                   mkvextract v90.0 (/usr/bin/mkvextract)
tesseract                    5.5.1 (/usr/bin/tesseract)
tesseract languages          eng, osd, por
...

Everything that pgsrip needs is installed.

The command exits with code 1 if something is missing, and prints how to install it.

Subtitle sample

A PGS subtitle holds two different things: the segments that say when and where a subtitle is shown, and the images that hold the text. Only the images hold the content of your media, and most bugs are in the first part.

pgsrip scrub writes a copy of your PGS subtitles without the images:

$ pgsrip scrub mymedia.mkv
pgsrip-a25b6c81.en.sup written: 1043/1043 display sets, 1043/1043 images redacted, 412088 bytes
The scrubbed files hold no subtitle image, only timing, layout and palettes.
Attach them to a new issue: https://github.com/ratoaq2/pgsrip/issues

The result is a real .sup file. pgsrip reads it through the very same code, so it reproduces the bug, but there is no text to read on it and it is much smaller than the original. The file name is a hash of the name of your media file. Use --keep-name to keep the original name.

If the bug is about the OCR itself, an empty image reproduces nothing. There are two other options:

$ pgsrip scrub --redact synthetic mymedia.mkv
$ pgsrip scrub --keep-images 412 mymedia.mkv

--redact synthetic draws placeholder text in each subtitle image, with the same size and the same palette as the original. --keep-images keeps the original image of the given display sets only, e.g. 412 or 400-420. A few subtitle lines are usually enough, and they stay small.

--only 0-99 writes only the given display sets, to cut a long subtitle short.

Debug log

--debug prints debug messages to the console. --log-file writes the same messages to a file, so you can attach it to a bug report:

$ pgsrip --log-file pgsrip.log mymedia.mkv
1 PGS subtitle collected from 1 file
Ripping subtitles  [####################################]  100%  mymedia.mkv [4:en]
1 PGS subtitle ripped from 1 file
Debug log written to pgsrip.log

The log starts with the pgsrip, Python and tesseract versions. It contains the paths of the files that were ripped. Remove or replace them if you do not want to share the names of your media files.

Metadata

Release files for pgsrip 0.1.13

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pgsrip 0.1.13
File Size Uploaded
pgsrip-0.1.13.tar.gz 137.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for pgsrip 0.1.13
File Interpreter ABI Platform
pgsrip-0.1.13-py3-none-any.whl Python 3 none any Details

Total release size: 174.5 kB

Release files / pgsrip-0.1.13.tar.gz

Download URL pgsrip-0.1.13.tar.gz
Size 137.3 kB
Tags Source
SHA-256 checksum
How to use checksums
6d7cb0d9571fec870506c464ce5f039f193e13008d9fa0911cede27c50d719bf
BLAKE2b-256 checksum
How to use checksums
cc6a2744f42ba0dfd8ba5a038b223491a5d3c0a0c222ba9bf3c3eab7d93f3ecc
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.17 {"installer":{"name":"uv","version":"0.12.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / pgsrip-0.1.13-py3-none-any.whl

Download URL pgsrip-0.1.13-py3-none-any.whl
Size 37.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
00518fc47317de9a3ebb270814b3eadeba3e6c35decd54804ff0eed0fc3244d6
BLAKE2b-256 checksum
How to use checksums
5abbd1837a52d50ef5e2334244eb9b27c68c3422c41b506be0f30dd1a88b695e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.17 {"installer":{"name":"uv","version":"0.12.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release history Release notifications | RSS feed

0.3.0

2 release files

0.2.1

2 release files

0.2.0

2 release files

This release

0.1.13 This release

2 release files

0.1.12

2 release files

0.1.11

2 release files

0.1.10

2 release files

0.1.9

2 release files

0.1.8

2 release files

0.1.7

2 release files

0.1.6

2 release files

0.1.5

2 release files

0.1.4

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.1

1 release file

0.1

1 release file

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page