Python: captionbob.render
captionbob.render.command_line
The command line of captionbob: one JSON request in, JSON lines out.
Run from the repo root with the Python of captionbob_env:
python -m captionbob.render.command_line <action> < request.json
A style is an effect of captionbob/effects. The actions and their requests:
list-styles No request. Each style with its settings.
list-plugins No request. Each plugin with its settings.
probe {"ffprobe_path", "video_path"}. The facts of a video.
transcribe {"video_path"}, and "model_name" and "compute_type" when
they are not the defaults of WhisperSettings. The
transcript of a video.
build-script {"version", "video", "ffmpeg_path", "work_folder"}, and
"emoji_index_folder", which an effect with emoji layers
needs. The ASS script of a video version, and its emoji
layers for the live preview in the form of
captionbob/render/preview_layers.py.
burn {"version", "video", "video_path", "output_path",
"ffmpeg_path", "work_folder"}, and "emoji_index_folder",
which an effect with emoji layers needs. The captioned
video.
"version" is the JSON object of captionbob/render/video_version.py. "video" is the object that probe gives: {"width", "height", "frame_rate", "duration_seconds", "has_audio"}, with the frame rate as a text such as "25/1". The work folder must exist, and one build-script or burn at a time may use it, because the caption measure and the burn write files of fixed names in it.
The emoji keywords of a style with emoji layers are the nouns, the proper nouns and the adjectives of the transcript, which the Stanza model of its language in the folder stanza of the emoji index folder names. A language with no model there keeps the letter limit of the style, and the emoji matcher compares every word. build-script and burn choose the keywords in the same way, so the preview shows the emoji of the burn.
Each line of the output is one JSON object with a "type":
"progress" {"type": "progress", "done_seconds", "total_seconds"},
while a burn or a transcription runs. A transcription
counts the seconds of audio, a burn the seconds of video.
"result" The result of the action, the last line when it works.
"error" {"type": "error", "message"}, the last line when it fails.
The exit code is 0 when the action works and 1 when it fails. The log goes to the standard error.
Source file: captionbob/render/command_line.py
write_line
def write_line(record: dict[str, Any]) -> None
Write one JSON object as one line of the standard output.
Args:
record: The object to write.
write_progress_line
def write_progress_line(done_seconds: float, total_seconds: float) -> None
Write one progress line of a burn or a transcription.
Args:
done_seconds: The seconds that are done.total_seconds: The seconds in all.
read_request
def read_request() -> dict[str, Any]
Read the JSON request of an action from the standard input.
Returns:
The request object.
Raises:
ValueError: When the input is not JSON or not a JSON object.
check_keys
def check_keys(
request: dict[str, Any], required: tuple[str, ...],
optional: tuple[str, ...], where: str = "The request") -> None
Refuse an object with a missing value or a value that is not known.
Args:
request: The request object, or an object inside it.required: The keys that the object must have.optional: The keys that the object may have.where: The name of the object, for the error text.
Raises:
ValueError: When a required key is missing, or when a key is not known.
text_value
def text_value(request: dict[str, Any], key: str) -> str
Give a text value of a request.
Raises:
TypeError: When the value is not a text.ValueError: When the text is empty.
path_value
def path_value(request: dict[str, Any], key: str) -> Path
Give a path value of a request.
Raises:
TypeError: When the value is not a text.ValueError: When the text is empty.
video_facts_record
def video_facts_record(probed: ProbedVideo) -> dict[str, Any]
Give the facts of a video as the JSON object of the actions.
Args:
probed: The facts of a video.
Returns:
The object with the keys VIDEO_FACT_KEYS. The frame rate is a text such as 25/1.
video_facts
def video_facts(record: Any) -> ProbedVideo
Read the facts of a video from the JSON object of the actions.
Args:
record: The object with the keys VIDEO_FACT_KEYS.
Returns:
The facts of the video.
Raises:
TypeError: When a value has the wrong type.ValueError: When a value is missing, not known or impossible.
list_styles
def list_styles() -> dict[str, Any]
Give each style with its settings.
Returns:
The result object. Each style has its name, whether it draws emoji layers next to its script, and each setting with its type and its default.
list_plugins
def list_plugins() -> dict[str, Any]
Give each plugin with its settings.
Returns:
The result object. Each plugin has its name, whether it reads the sound of the video, and each setting with its type and its default.
probe
def probe(request: dict[str, Any]) -> dict[str, Any]
Give the facts of a video.
Args:
request: The request with FFPROBE_PATH_KEY and VIDEO_PATH_KEY.
Returns:
The result object with the facts of the video.
transcribe
def transcribe(request: dict[str, Any]) -> dict[str, Any]
Give the transcript of a video, with progress lines.
Args:
request: The request with VIDEO_PATH_KEY, and MODEL_NAME_KEY and COMPUTE_TYPE_KEY when they are not the defaults.
Returns:
The result object with the JSON object of the transcript.
Raises:
FileNotFoundError: When the video is not a file. The request is checked before the model is loaded on the GPU.
emoji_index_folder
def emoji_index_folder(
request: dict[str, Any], effect_name: str, action: str) -> Path
Give the emoji index folder of a request for an effect with emoji layers.
Args:
request: The request.effect_name: The name of the effect, for the error text.action: What needs the folder, such as the burn, for the error text.
Returns:
The emoji index folder.
Raises:
ValueError: When the request has no emoji index folder, so that no emoji is left out without a word.
emoji_script
def emoji_script(
version: VideoVersion, video: VideoInfo,
caption_measure: CaptionMeasure,
index_folder: Path) -> tuple[str, tuple[Any, ...]]
Build the ASS script and the keyword emoji layers of a version whose effect draws emoji layers.
The Stanza model of the language of the transcript names its nouns, proper nouns and adjectives. They choose the captions of an effect that takes a keyword picker, and they are the only words that the emoji matcher compares. A language with no Stanza model in the emoji index folder keeps the default picker of the effect, with its letter limit, and the matcher compares every word.
Args:
version: The video version.video: The frame size, the frame rate and the duration of the video.caption_measure: The caption measure of the effect.index_folder: The emoji index folder.
Returns:
The text of the ASS script and the emoji layers.
Raises:
FileNotFoundError: When the emoji index folder has no Stanza resources file, or when a file of the index or of a model is missing.
build_script
def build_script(request: dict[str, Any]) -> dict[str, Any]
Give the ASS script of a video version and its emoji layers.
An effect with emoji layers gets the script and the layers that its burn gets, so the live preview shows what the burn draws.
Args:
request: The request with VERSION_KEY, VIDEO_KEY, FFMPEG_PATH_KEY and WORK_FOLDER_KEY, and EMOJI_INDEX_FOLDER_KEY for an effect with emoji layers.
Returns:
The result object with the text of the ASS script and the record of each emoji layer for the preview. An effect with no emoji layers has no layer records.
Raises:
ValueError: When an effect with emoji layers has no emoji index folder.
burn
def burn(request: dict[str, Any]) -> dict[str, Any]
Burn a video version on its video, with progress lines.
A new video that is only partly written when the burn fails is removed.
Args:
request: The request with VERSION_KEY, VIDEO_KEY, VIDEO_PATH_KEY, OUTPUT_PATH_KEY, FFMPEG_PATH_KEY and WORK_FOLDER_KEY, and EMOJI_INDEX_FOLDER_KEY for an effect with emoji layers.
Returns:
The result object with the path of the new video.
Raises:
ValueError: When an effect with emoji layers has no emoji index folder.NotADirectoryError: When the folder of the new video is not a folder.RuntimeError: When ffmpeg fails.
run_action
def run_action(action: str) -> dict[str, Any]
Run one action and give its result object.
Args:
action: One of ACTIONS.
Returns:
The result object of the action.
Raises:
ValueError: When the action is not known.
main
def main(arguments: list[str] | None = None) -> int
Run the command line.
Args:
arguments: The command line arguments. None takes them from the command line of the process.
Returns:
EXIT_DONE when the action works, EXIT_FAILED when it fails. A failure writes an error line and logs its trace.