Media generation
The media generators of skai.generation return one image, audio sample or video per sample, of the type their name
ends with, in the requested output_format. Every generator takes an operation from its own set, validated at
fit. Fixed conditioning, such as a voice or a portrait, stays in constructor parameters, and conditioning that
changes per sample is a key of a multimodal sample.
| Class | operation, default first |
|---|---|
TextToImageGenerator |
'generate' |
ImageToImageGenerator |
'edit', 'upscale', 'remove_background', 'collage' |
VideoToImageGenerator |
'thumbnail', 'frame' |
MultimodalToImageGenerator |
'edit' |
TextToAudioGenerator |
'speech', 'music', 'sound' |
AudioToAudioGenerator |
'separate', 'enhance', 'convert_voice', 'concatenate' |
VideoToAudioGenerator |
'extract' |
MultimodalToAudioGenerator |
'mix', 'speech' |
TextToVideoGenerator |
'generate' |
ImageToVideoGenerator |
'animate' |
AudioToVideoGenerator |
'talking_head' |
VideoToVideoGenerator |
'reframe', 'concatenate' |
MultimodalToVideoGenerator |
'lip_sync', 'mux', 'subtitle' |
An operation that the class does not offer raises InvalidParameterError listing the valid ones, and an operation
that the backend does not support raises UnsupportedBackendError at fit, listing the backends that do.
Local operations
collage, frame, concatenate, extract, mix, mux and subtitle are deterministic media operations that run
locally, without a backend or credentials. Video operations need the video extra. The first version holds whole
videos in memory, so long videos need much memory.
Images
TextToImageGenerator creates one image of size per prompt, with an optional style and negative_prompt.
reference_images show a subject that every image keeps consistent, on backends that take reference images.
ImageToImageGenerator edits every image with one fixed instructions inside an optional mask, upscales by
scale, removes the background into a transparent image, or lays a list of images out as a collage.
from PIL import Image
from skai.generation import ImageToImageGenerator, TextToImageGenerator
generator = TextToImageGenerator(size=(64, 48), style='watercolor', random_state=0, backend='dummy')
image = generator.fit().predict(['a lake'])[0]
edited = ImageToImageGenerator(instructions='add snow', backend='dummy').fit().predict([image])[0]
upscaled = ImageToImageGenerator(operation='upscale', scale=2, backend='dummy').fit().predict([image])[0]
cutout = ImageToImageGenerator(operation='remove_background', backend='dummy').fit().predict([image])[0]
collage = ImageToImageGenerator(operation='collage', tile=32).fit().predict([[image, edited, upscaled]])[0]
print(edited.size, upscaled.size, cutout.mode, collage.size)
(64, 48) (128, 96) RGBA (64, 64)
VideoToImageGenerator returns the thumbnail that the backend picks among n_frames sampled frames, or the frame at
at seconds. MultimodalToImageGenerator edits the image of every sample with the instructions of the same
sample, inside its optional mask, so every image gets its own edit.
import numpy as np
from PIL import Image
from skai.core import Video
from skai.generation import MultimodalToImageGenerator, VideoToImageGenerator
video = Video(np.zeros((8, 48, 64, 3), dtype=np.uint8), fps=4)
thumbnail = VideoToImageGenerator(n_frames=4, backend='dummy').fit().predict([video])[0]
frame = VideoToImageGenerator(operation='frame', at=1.0).fit().predict([video])[0]
mask = Image.new('L', (64, 48), 255)
sample = {'image': Image.new('RGB', (64, 48)), 'instructions': 'Write Γεια here.', 'mask': mask}
print(thumbnail.size, frame.size, MultimodalToImageGenerator(backend='dummy').fit().predict([sample])[0].size)
(64, 48) (64, 48) (64, 48)
Audio
TextToAudioGenerator speaks every text in voice and language, or creates music or a sound of duration
seconds that the text describes. A string voice names a voice of the backend, and reference audio clones a voice on
backends that support it.
from skai.generation import TextToAudioGenerator
speech = TextToAudioGenerator(voice='alloy', backend='dummy').fit().predict(['Welcome to scikit-ai.'])[0]
music = TextToAudioGenerator(operation='music', duration=2, backend='dummy').fit().predict(['calm piano'])[0]
sound = TextToAudioGenerator(operation='sound', duration=1, backend='dummy').fit().predict(['a door slams'])[0]
print(speech, music, sound)
Audio(duration=0.50s, sample_rate=16000) Audio(duration=2.00s, sample_rate=16000) Audio(duration=1.00s, sample_rate=16000)
AudioToAudioGenerator returns the stem of a separation, 'vocals' or 'accompaniment', a denoised copy, the
same speech in another voice, or a list of audio samples joined with gap seconds between them.
VideoToAudioGenerator returns the mono audio track of every video, or silence as long as a video without one.
import numpy as np
from skai.core import Video
from skai.generation import AudioToAudioGenerator, VideoToAudioGenerator
song = (0.3 * np.sin(np.arange(32000) / 10), 16000)
vocals = AudioToAudioGenerator(operation='separate', stem='vocals', backend='dummy').fit().predict([song])[0]
clean = AudioToAudioGenerator(operation='enhance', backend='dummy').fit().predict([song])[0]
converted = AudioToAudioGenerator(operation='convert_voice', voice=song, backend='dummy').fit().predict([song])[0]
joined = AudioToAudioGenerator(operation='concatenate', gap=0.5).fit().predict([[song, song]])[0]
track = VideoToAudioGenerator().fit().predict([Video(np.zeros((8, 8, 8, 3), dtype=np.uint8), fps=4)])[0]
print(vocals, clean, converted, joined, track)
Audio(duration=2.00s, sample_rate=16000) Audio(duration=2.00s, sample_rate=16000) Audio(duration=2.00s, sample_rate=16000) Audio(duration=4.50s, sample_rate=16000) Audio(duration=2.00s, sample_rate=16000)
MultimodalToAudioGenerator(operation='mix') mixes the named tracks of every sample into one track as long as the
longest. volumes sets the gain of every track, and the tracks in duck_under are lowered to duck_level while the
track duck_for sounds. A track is audio, a video whose audio track is used, or a list of timed records with start
and media, such as segmenter regions, each placed at its start. With operation='speech', it speaks the text of
every sample in the voice of the same sample, a voice name or reference audio.
import numpy as np
from skai.generation import MultimodalToAudioGenerator
voice = (0.3 * np.sin(np.arange(16000) / 10), 16000)
music = (0.1 * np.sin(np.arange(48000) / 30), 16000)
mixer = MultimodalToAudioGenerator(volumes={'music': 0.5}, duck_under=['music'], duck_for='voice').fit()
print(mixer.predict([{'voice': voice, 'music': music, 'effect': [{'start': 2.0, 'media': voice}]}]))
speaker = MultimodalToAudioGenerator(operation='speech', backend='dummy').fit()
print(speaker.predict([{'text': 'Hello.', 'voice': 'alloy'}, {'text': 'Hi there.', 'voice': voice}]))
[Audio(duration=3.00s, sample_rate=16000)]
[Audio(duration=0.30s, sample_rate=16000)
Audio(duration=0.40s, sample_rate=16000)]
Video
TextToVideoGenerator creates one video per prompt, of duration seconds and size pixels. ImageToVideoGenerator
turns every image into a short video that starts from it, with optional instructions for the motion.
AudioToVideoGenerator makes a fixed avatar speak every audio sample, as a talking head with the audio as its
track. Backends with fixed video lengths or sizes, such as Sora, generate the closest and trim and resize the result,
which needs the video extra.
import numpy as np
from PIL import Image
from skai.generation import AudioToVideoGenerator, ImageToVideoGenerator, TextToVideoGenerator
video = TextToVideoGenerator(duration=2, size=(64, 48), fps=8, backend='dummy').fit().predict(['a boat at sea'])[0]
animator = ImageToVideoGenerator(instructions='slow zoom in', duration=1, fps=8, backend='dummy').fit()
talking = AudioToVideoGenerator(avatar=Image.new('RGB', (64, 64), 'beige'), backend='dummy').fit()
print(video, animator.predict([Image.new('RGB', (64, 48))])[0], talking.predict([(np.zeros(16000), 16000)])[0])
Video(duration=2.00s, fps=8) Video(duration=1.00s, fps=8) Video(duration=1.00s, fps=25)
VideoToVideoGenerator(operation='reframe') crops every video to aspect_ratio, following the subject that the
backend detects in n_frames sampled frames, and operation='concatenate' joins a list of clips at the size and frame
rate of the first. MultimodalToVideoGenerator lip-syncs video to audio, replaces the soundtrack of video with
audio, or shows transcript as subtitles. A transcript is a string, or a list of timed records with start, end
and text, such as the regions of AudioSegmenter. Subtitles are burned into the frames, or with burn=False
attached as subtitles in SRT format and written next to the video.
import numpy as np
from skai.core import Video
from skai.generation import MultimodalToVideoGenerator, VideoToVideoGenerator
clip = Video(np.zeros((8, 48, 64, 3), dtype=np.uint8), fps=4)
speech = (np.zeros(32000), 16000)
vertical = VideoToVideoGenerator(aspect_ratio=9 / 16, backend='dummy').fit().predict([clip])[0]
joined = VideoToVideoGenerator(operation='concatenate').fit().predict([[clip, clip, clip]])[0]
synced = MultimodalToVideoGenerator(backend='dummy').fit().predict([{'video': clip, 'audio': speech}])[0]
muxed = MultimodalToVideoGenerator(operation='mux').fit().predict([{'video': clip, 'audio': speech}])[0]
subtitler = MultimodalToVideoGenerator(operation='subtitle', burn=False).fit()
subtitled = subtitler.predict([{'video': clip, 'transcript': [{'start': 0.0, 'end': 1.5, 'text': 'Hello.'}]}])[0]
print(vertical.frames.shape, joined, synced, muxed.audio)
print(subtitled.subtitles)
(8, 48, 27, 3) Video(duration=6.00s, fps=4) Video(duration=2.00s, fps=4) Audio(duration=2.00s, sample_rate=16000)
1
00:00:00,000 --> 00:00:01,500
Hello.
Responsible use
Cloned voices, converted voices, lip sync and talking heads can imitate real people. Generate them only with the consent of the people they depict, label them as generated where they are shared, and follow the usage policies of the provider that runs the model.
What fit learns
Media generators prepare their conditioning in fit:
TextToAudioGeneratorandAudioToAudioGenerator(operation='convert_voice')join one or more recordings invoiceintovoice_. Backends that cannot clone voices raiseUnsupportedBackendErroratfit.TextToImageGeneratorlearnsstyle_fromstyle_images, written by the backend's image description, and an explicitstyletakes precedence. Withreference_prompt, it generatesreference_images_and sends them with every request, and explicitreference_imagestake precedence.AudioToVideoGeneratorpreparesavatar_: converted to RGB, center-cropped to a square, and resized to the input size of the backend.ImageToImageGeneratorreadsmaskintomask_.
from PIL import Image
from skai.generation import TextToImageGenerator
references = [Image.new('RGB', (16, 16), color) for color in ('teal', 'navy')]
styled = TextToImageGenerator(size=(64, 48), style_images=references, backend='dummy').fit()
consistent = TextToImageGenerator(size=(64, 48), reference_prompt='a girl with a red scarf', backend='dummy').fit()
print(styled.style_, len(consistent.reference_images_))
A 16x16 image. A 16x16 image. 1
The API reference is in skai.generation.