Back to Posts
Illustrated concept of Bragir, the Python-Based CLI for Transcribing and Translating Videos using OpenAI, depicted as a regal figure with a harp, evoking the tool's elegance and proficiency.

Python CLI: Easy Video Subtitling with AI

By Andreas Bergman

The creation of Bragir, our own Command Line Interface (CLI), a translation tool by ArjanCodes, is developed using Python, AI, and the Click package. But why? To give some background, the Arjancodes channel has a lot of YouTube videos that are all in English. However, not everyone has English as their mother tongue. Therefore, it would be nice to add a closed caption in different languages to help the viewer. So, I solved this in a more fun way than doing it manually, which resulted in Bragir.

Before the project started, it had some requirements:

  • Transcribe a .mp3 or .mp4 video of any size into an SRT file.
  • Translate an SRT file of any size into one or many languages.
  • Languages that need to be supported are German, Spanish, Polish, Portuguese, French, Italian, and Swedish.

The reason behind the stack

By using the package Click, we created the structure and scaffolding of Bragir. Click also helps with the generation of the help text, handling arguments, options, and more! Which was very convenient!

With Poetry, we easily managed the dependencies and publishing of the package to PyPI. If you want to learn more about Poetry, check out the following blog post.

To perform the translation and transcription, Bragir calls the OpenAI services whisper and GPT-4. Whisper does the transcribing of the video, resulting in an SRT file. While the translation or the SRT file is using GPT-4. Using one service for both translation and transcription makes it easier to implement the tool. However, with some design patterns, different services could be used. But for now, it is OPENAI all the way!

How this was implemented

Poetry was used to set up the scaffolding and project structure.

> poetry new bragir

Resulting in the following package structure:

bragir/
|- bragir/
|  |
|  |- __init__.py
|
|- tests/
|  |
|  |- __init__.py
|
|- pyproject.toml
|- README.md

Packages such as Click and OpenAI were added to the project using Poetry.

> poetry add click openai

After that, we were ready to start coding! Two commands were created: translate and transcribe. Both commands are going to be defined in ./bragir/commands.py

import os
import click

@click.command()
@click.option(
"--file_path", "-f", required=True, type=click.Path(exists=True, file_okay=True)
)
@click.option("--output_path", "-o", type=click.Path(file_okay=True))
@click.option(
	"--api_key",
	"-k",
	required=True,
	envvar="OPENAI_API_KEY",
	help=PROMPT_HELP["api_key"],
)
def transcribe(file_path: str, output_path: str, api_key: str) -> None:
	transcriber = initiate_client(api_key=api_key)
	...

@click.command()
@click.option(
	"--file",
	"-f",
	type=click.Path(dir_okay=True, exists=True),
	prompt="Enter path to file",
	help=PROMPT_HELP["file"],
)
@click.option(
	"--api_key",
	"-k",
	required=True,
	envvar="OPENAI_API_KEY",
	help=PROMPT_HELP["api_key"],
)
@click.option(
	"--directory",
	"-d",
	type=click.Path(dir_okay=True, exists=True),
	help=PROMPT_HELP["directory"],
)
@click.option(
	"--language",
	"-l",
	required=True,
	type=click.Choice([language.value for language in Languages], case_sensitive=False),
	multiple=True,
	help=PROMPT_HELP["language"],
)

def translate(file: str, api_key: str, language: str, directory: str) -> None:
	translator = initiate_client(api_key=api_key)
	...

This post will not go through all the code, because then it would never end! If you want to see all the code that was written, check out the following github repository. Furthermore, if you want to learn more about the Click package, I would recommend you read the following blog post that covers how to create a basic CLI tool using Click.

In order to access transcribe and translate, we added them as Click commands to the ./bragir/__main__.py because it acts as the entry point for the script. By using click.group() we attach transcribe and translate as subcommands to the command bragir. So the user can use the following commands:

> bragir translate ...
# OR
> bragir transcribe ...

In order to access the commands, we add them to the click group cli . This will make the commands accessable from the CLI, as showed above.

# ./bragir/__main__.py

import click
from . import commands

@click.group()
def cli():
	pass

cli.add_command(commands.translate)
cli.add_command(commands.transcribe)

And the outline of the package is done! In order to test the tool, build and install the package locally using Poetry.

Build and publish

Bragir is open source, meaning that anyone can help develop this CLI tool, but it also means that anyone can use this tool for free! However, in order to let people access the tool, it needs to be built and published. Poetry was the solution. Poetry, with the help of the pyproject.toml file, can create .whl files and tar balls for easier distribution. Furthermore, it has built-in commands to publish the tool to PyPI.

First, Bragir was built.

> poetry build

This resulted in a ./dist directory in the root directory that contains one tarball and one whl file.

Then Bragir was published.

> poetry publish --build

Bragir is now accessible to anyone and can be easily installed using pip! If you want to help develop Bragir, then make a PR or issue so we can develop and create the best CLI tool for video closed caption!

Try it out!

If you want to try out Bragir, you will need to follow the installation guide on the github page. For now, the two hurdles that are needed to be overcome are having to install FFmpeg on your system and having an OpenAI key. After that, you are all set to use Bragir!

Improve your code with my 3-part code diagnosis framework

Watch my free 30 minutes code diagnosis workshop on how to quickly detect problems in your code and review your code more effectively.

When you sign up, you'll get an email from me regularly with additional free content. You can unsubscribe at any time.

Recent posts