Skip to content

Recipes

skai.recipes holds functions that return configured pipelines, from a brief to an explainer video or from a video to the same video dubbed in another language. Every recipe returns an ordinary scikit-learn Pipeline built only from the public components, the primitives of skai.pipeline and scikit-learn, so its steps can be inspected, changed with set_params, cloned and tuned. video_search returns a Retriever instead, since it answers queries.

Every recipe takes a backend, passed to every step that uses one, and keyword arguments for its main choices. The examples run on dummy with tiny inputs. Replace backend='dummy' with a provider, or leave it out to use hf, to get real results. Some steps need a provider that offers their operation, as Backends lists.

from skai import recipes

pipeline = recipes.explainer_video(backend='dummy')
print([name for name, _ in pipeline.steps])
pipeline.set_params(plan__scenes__instructions='Split the text into two scenes.')
print(pipeline.get_params()['plan__scenes__instructions'])
['plan', 'media', 'tracks', 'muxed', 'subtitled']
Split the text into two scenes.

The examples share these inputs: a three-second video with one shot per second and a tone as its track, a recording of two seconds, and small photos.

import numpy as np
from PIL import Image
from skai import recipes
from skai.core import Audio, Video

frames = np.zeros((24, 48, 64, 3), dtype=np.uint8)
for index in range(24):
    frames[index] = (index // 8) * 90
tone = Audio((0.3 * np.sin(np.arange(48000) / 10)).astype(np.float32), 16000)
video = Video(frames, fps=8, audio=tone)
recording = (0.3 * np.sin(np.arange(32000) / 10), 16000)
photos = [Image.new('RGB', (64, 48), color) for color in ('red', 'blue')]
print(video, recording[0].shape, photos[0].size)
Video(duration=3.00s, fps=8) (32000,) (64, 48)

Brief to explainer video

explainer_video turns a brief into one narrated, subtitled video with music. A storyboard from TextExtractor splits the brief into scenes, every scene gets a generated image animated into a clip and a spoken narration, the clips and narrations are joined, music is mixed under the narration, and the narration is burned in as subtitles.

explainer = recipes.explainer_video(size=(64, 48), scene_seconds=1, backend='dummy')
(result,) = explainer.fit(None).predict(['How solar panels work'])
print(result, result.audio, result.subtitles is not None)
Video(duration=2.00s, fps=8) Audio(duration=2.00s, sample_rate=16000) True

Articles to podcast

podcast turns an article into one audio episode: a summary, a script of two hosts, every line spoken in the voice of its host, the lines joined in order, and generated music mixed under them.

podcast = recipes.podcast(voices=('alloy', 'echo'), music_seconds=2, backend='dummy')
print(podcast.fit(None).predict(['Bees pollinate flowers in spring.']))
[Audio(duration=2.00s, sample_rate=16000)]

Post to vertical clip

vertical_clip turns a post into a short vertical video: a shortened script, the steps of the explainer video, reframing to 9:16 following the main subject, and burned subtitles.

vertical = recipes.vertical_clip(size=(64, 48), scene_seconds=1, backend='dummy')
(clip,) = vertical.fit(None).predict(['A post about running'])
height, width = clip.frames.shape[1:3]
print(clip, round(height / width, 2))
Video(duration=2.00s, fps=8) 1.78

Story to read-along video

read_along turns a story into a video whose characters, described by characters, look the same on every page. fit generates one reference image of the characters, which every page image keeps consistent, and the narration is shown word by word.

story = recipes.read_along(characters='a girl and her dog', size=(64, 48), page_seconds=1, backend='dummy')
print(story.fit(None).predict(['A girl and her dog walk to the sea.']))
[Video(duration=2.00s, fps=8)]

Product photos to catalog and ads

product_catalog removes the background of every photo and extracts its attributes and a short marketing text. product_ad edits every photo into a scene, upscales it and animates it into a promotional clip.

records = recipes.product_catalog(backend='dummy').fit(None).predict(photos)
print(list(records[0]))
print(recipes.product_ad(duration=1, backend='dummy').fit(None).predict(photos))
['name', 'category', 'color', 'material', 'copy']
[Video(duration=1.00s, fps=8) Video(duration=1.00s, fps=8)]

Dubbing in the original voice

dubbing turns a video into the same video speaking another language in the original voice. The speech is transcribed and translated, the vocals and the accompaniment are separated, the translation is spoken in the voice of the vocals, the video is lip-synced to it, the accompaniment is mixed back, and subtitles in the new language are burned in.

(dubbed,) = recipes.dubbing(target_language='Greek', backend='dummy').fit(None).predict([video])
print(dubbed, dubbed.duration == video.duration)
Video(duration=3.00s, fps=8) True

Image text translation

image_translation redraws the text of images, such as comics or screenshots, in another language. The text of every image is transcribed and translated into an edit instruction, the text regions are masked, and the image is edited inside the mask.

(translated,) = recipes.image_translation(target_language='Greek', backend='dummy').fit(None).predict(photos[:1])
print(translated.size)
(64, 48)

Meeting to briefing

meeting_briefing turns a meeting recording into a dict with minutes, a list of action_items with owners, and video, a short briefing read by a talking head.

(briefing,) = recipes.meeting_briefing(avatar=photos[0], backend='dummy').fit(None).predict([recording])
print(list(briefing), briefing['action_items'][0], briefing['video'])
['minutes', 'action_items', 'video'] {'owner': 'seconds.', 'task': 'seconds.', 'due': 'of'} Video(duration=0.60s, fps=25)

Call analytics

call_topics labels the topic and sentiment of every speaker turn of recorded calls and clusters the turns by meaning. It is fitted on recordings, and returns one list of turn records per call.

calls = [recording, (0.2 * np.cos(np.arange(48000) / 7), 16000)]
turns = recipes.call_topics(n_clusters=2, backend='dummy').fit(calls).predict(calls)
print([sorted(turn) for turn in turns[0]])
[['cluster', 'sentiment', 'speaker', 'text', 'topic'], ['cluster', 'sentiment', 'speaker', 'text', 'topic']]

Invoices to anomaly scores

invoice_anomalies extracts the vendor, amount and date of every invoice scan and scores them with an IsolationForest, which returns 1 for normal and -1 for anomalous scans.

scans = [Image.new('RGB', (64, 48), color) for color in ('red', 'blue', 'green', 'white')]
print(recipes.invoice_anomalies(backend='dummy').fit(scans).predict(scans))
[-1  1  1  1]

Searching a video library by text

video_search returns a Retriever that splits every video into shots, embeds the shots and the text queries with one joint text and image model, CLIP on Hugging Face by default, and returns the closest shots of every query with the index of their video as sample, their start and end, and their distance.

search = recipes.video_search(backend='dummy').fit([video, video])
(shots,) = search.kneighbors(['a goal'], n_neighbors=2)
print([(shot['sample'], shot['start'], shot['end']) for shot in shots])
[(0, 2.0, 3.0), (1, 2.0, 3.0)]

Multimodal moderation

moderation classifies posts given as multimodal samples of an image and a caption, judging both in one request, with labeled posts as few-shot examples and probabilities calibrated by cross-validation.

posts = [{'image': photos[index % 2], 'caption': f'caption {index}'} for index in range(4)]
moderation = recipes.moderation(cv=2, backend='dummy').fit(posts, ['safe', 'unsafe'] * 2)
print(moderation.predict_proba(posts).shape)
(4, 2)

Audio description track

audio_description adds a spoken description of every shot to a video, placed at the start of the shot, with the dialogue lowered while it plays, plus subtitles of the dialogue.

(described,) = recipes.audio_description(max_length=5, backend='dummy').fit(None).predict([video])
print(described, described.duration == video.duration)
Video(duration=3.00s, fps=8) True

Lecture to study pack

study_pack turns a lecture video into a dict with notes, key_terms, a quiz and recap, a narrated audio summary.

(pack,) = recipes.study_pack(n_questions=2, backend='dummy').fit(None).predict([video])
print(list(pack), pack['recap'])
['notes', 'key_terms', 'quiz', 'recap'] Audio(duration=0.60s, sample_rate=16000)

Visual quality control

quality_control classifies product photos as defective or not. A visual question answer about defects and the detected defect regions of every photo are combined into the features of a logistic regression trained on labeled photos.

inspection = recipes.quality_control(defects=['scratch', 'dent'], backend='dummy')
print(inspection.fit(photos * 2, ['ok', 'defective'] * 2).predict(photos))
['defective' 'defective']

Highlight reel

highlights turns a long video into a reel of its k most exciting shots in their original order, with generated music mixed in.

(reel,) = recipes.highlights(k=2, music_seconds=2, backend='dummy').fit(None).predict([video])
print(reel)
Video(duration=2.00s, fps=8)

The API reference is in skai.recipes.