Jadpo is experimental and not ready for production. These docs follow the compiler's main branch as of 30 Oct 2026. What's built · Install 0.1.0
jadpo
Reference: Standard library

Standard library

Media

On this page

The media types describe images, video, audio and captions: an image's size, a frame rate, a timecode, a subtitle cue, a film's age rating. Each follows its own standard. As every standard type does, each is read only in its canonical text. None is ordered, and none is personal data.

Here a video library makes thumbnails, reads a film's age rating, shows where an edit starts and writes captions:

example
type FormText = Text {}type NotARating = Failure {    kind: FailureKind.invalid_value}/// A still's thumbnail: scaled to fit a 320-pixel square, never enlarged.function thumbnail(video_still: ImageDimensions) -> ImageDimensions {    var tile: ImageDimensions = ImageDimensions {        width: 320        height: 320    }    return media.fit(video_still, within: tile)}/// The age rating a film's form names.function film_rating(raw: FormText) fails NotARating -> ContentRating {    var typed_rating: ContentRating = attempt text.parse(raw, as: ContentRating) {        malformed: NotARating        rating_of_scheme: NotARating    }    return typed_rating}/// Where an edit starts, as the edit list shows it.function edit_start(edit_point: Timecode) -> PresentationText {    return text.format(edit_point, locale: Locale.en_gb)}/// A caption as a WebVTT file writes it.function caption_text(opening_caption: SubtitleCue) -> FormText {    return FormText(text.from(opening_caption))}
example
test "a thumbnail fits its tile and is never enlarged" {    var landscape: ImageDimensions = ImageDimensions {        width: 4000        height: 3000    }    var wide_still: ImageDimensions = ImageDimensions {        width: 1000        height: 333    }    var icon: ImageDimensions = ImageDimensions {        width: 200        height: 100    }    assert text.from(thumbnail(landscape)) == "320x240"    assert text.from(thumbnail(wide_still)) == "320x106"    assert thumbnail(icon) == icon}test "a rating is one of its body's categories" {    var given_rating: ContentRating = attempt film_rating("BBFC 12A")    assert given_rating.scheme == ContentRatingScheme.bbfc    assert film_rating("BBFC PG-13") fails NotARating    assert film_rating("12A") fails NotARating}test "a timecode is shown in SMPTE's notation, a cue as WebVTT writes it" {    var edit_point: Timecode = Timecode {        hours: 1        minutes: 10        seconds: 0        frames: 0        rate: FrameRate {            numerator: 30000            denominator: 1001        }        drop_frame: true    }    assert edit_start(edit_point) == "01:10:00;00"    var opening_caption: SubtitleCue = SubtitleCue {        start: 1s        end: 4s        text: "Mind the gap."    }    assert caption_text(opening_caption) == "00:00:01.000 --> 00:00:04.000\nMind the gap."}

Fitting an image into a box

Operation Gives Fails SQL form
media.fit(dimensions, within:) ImageDimensions scaled to fit inside within, keeping the aspect ratio, never larger than the original, rounded down to whole pixels and never below 1 none

media.fit works as CSS's object-fit: scale-down does, in whole numbers. The side that limits the fit becomes exactly the box's size. The other side is scaled with it and rounded down, never below 1. An image that already fits is kept as it is, never enlarged.

Sizes, ratios and frame rates

  • An ImageDimensions and a VideoResolution are a width and a height in whole pixels, from 1 to 2,147,483,647. That is PNG's limit, the largest of the common formats'. Each is written 1920x1080, width first, with a lower-case x. Each is sent as named fields, so nothing reads them the wrong way round, and stored as a column each.
  • A VideoResolution has the same shape under its own name. It names a resolution by its pixels, never by a name like "4K", which means both 3840 and 4096 pixels across.
  • An AspectRatio is a width and a height, whole numbers from 1, written 16:9. It is held as written, as a Ratio is, so 16:9 and 32:18 are two different values. It is sent as its text and stored as a column each. A cinema's 2.39:1 is written 239:100. A later release can accept decimals without changing any value.
  • A FrameRate is a numerator and a denominator, each from 1 to 2,147,483,647, written 30000/1001 or 25/1. The denominator is always written, and the rate is held as written. It is sent as its text and stored as a column each.

Boxes, paper and orientation

  • A Rect is an x and a y, each any Decimal, and a width and a height, never below 0. Its text is SVG's viewBox: 0 0 300 200.
  • An Insets is a top, right, bottom and left, each never below 0, so a negative margin is refused. Its text is the CSS box model's four sides: 8 16 8 16.
  • In both texts each number keeps the places it was given, has no leading zero, and is one space from the next, and every part is always written. Each is sent as named fields and stored as a column per part.
  • A PaperSize is one of ISO 216's A0 to A10 and B0 to B10, or ANSI/ASME Y14.1's letter, legal and tabloid, coded A4 or Letter. ISO 269's envelope sizes and ledger (tabloid on its side) are left out.
  • An ExifOrientation says how a stored image must be turned to show it upright. Its variants are named for where the stored image's first row and column are seen, as libtiff names TIFF 6.0's values: top_left to left_bottom. They are coded 1 to 8 and sent as that text, as every enum is sent as its code.
  • An AltText is one line of an image's text alternative, as WCAG describes it: 1 to 1,000 characters, with no space at either end. An image with nothing to say has none in a field that may be empty, never empty text.

Codecs

A VideoCodec and an AudioCodec are the codec strings the W3C WebCodecs Codec Registry lists, in RFC 6381's form, such as avc1.42001E or opus:

  • video: av01, avc1, avc3, hev1, hvc1 and vp09, each with its elements, and vp8;
  • audio: mp4a with its elements, flac, mp3, opus, vorbis, ulaw, alaw and the five pcm- forms.

The elements after the first aren't checked further. Case is kept, as the registry writes them.

Timecodes and subtitles

A Timecode is a position in a video as SMPTE ST 12-1 writes it: hours (0 to 23), minutes and seconds (0 to 59) and frames (0 to 119, room for 120 frames a second), with its rate and whether it counts drop_frame. Drop-frame timecode skips some frame labels so that the clock keeps time with a 29.97 frames-a-second video. A timecode has three rules:

  • frames_within_rate: its frames are below its rate's frames a second, rounded up to a whole number;
  • drop_frame_rate: drop-frame is used only at 30000/1001 and 60000/1001 frames a second, compared by value;
  • frame_not_dropped: a drop-frame timecode never names a label that drop-frame skips, frames 0 and 1 (or 0 to 3 at the higher rate) at the start of each minute except every tenth.

Its notation, 01:00:00;00, doesn't say its rate, so a timecode has no single text form. It is sent as its parts, stored as a column per part (its rate in two), and shown in that notation.

A SubtitleCue is a WebVTT cue: a start and an end, each a Duration from the start of the media to the millisecond, and its text, lines with no control character and no blank line. Its rules are start_not_negative, end_after_start and text_without_arrow, which refuses --> in the text. Its canonical text is the cue's timings line, its hours in two digits or more, then a line feed and its text, with no identifier or settings: 00:00:01.000 --> 00:00:04.000 and its text. It is sent as named fields and stored as a column per part.

When you write a Timecode or a SubtitleCue out as a literal, its rules are checked while compiling. A value read from JSON is checked as it is read. One built in code from other values is built with attempt, which fails by the rule it breaks.

Age ratings

A ContentRating is a scheme and a rating, one of that body's categories as it writes them, its rule rating_of_scheme. It is written BBFC 12A or PEGI 16, the body's code read ignoring case. It is sent as that text and stored as a column each.

The bodies are a standard enum, ContentRatingScheme:

  • BBFC: U, PG, 12A, 12, 15, 18, R18;
  • the MPA, the MPAA's name since 2019: G, PG, PG-13, R, NC-17;
  • PEGI: 3, 7, 12, 16, 18;
  • ESRB: E, E10+, T, M, AO, RP.

Other bodies, such as USK, the ACB and US television's, come with a later release.

Markdown for agents: /docs/media.md.Built from Jadpo main at a707efb.