Help us shape the future of Go! Take the 2026 Go Developer Survey

media

package
v0.135.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 28, 2026 License: MIT Imports: 23 Imported by: 1

Documentation

Overview

Package media stores application media in a private bucket. A registry declares media kinds, uploads, renditions and access. Each item has an ordered manifest that is authoritative for retained source and derived files. A database journal records conditional manifest writes, pending allocations and exact retirement effects, including interrupted uploads and caches.

Scoped roots are tenant/<tenant>/app/<app>/<kind>/<item>/; versioned content uses the version as the physical item ID. Account media uses tenant/<tenant>/account/. Legacy roots remain documented in media/layout.

Index

Constants

View Source
const (
	AccessFull = "full" // whole-item private access
)
View Source
const (
	AccessNone = "none" // public files only (previews)
)
View Source
const (
	AccessPartial = "partial" // exact authorized private files only
)
View Source
const AvatarPreset = "avatar"

AvatarPreset is the public preset a user-owned group's avatar shows.

View Source
const (
	CodeAnimationNotAllowed = "animation_not_allowed" // 422: an animated image where the policy is AnimationReject
)
View Source
const (
	CodeAnimationTooLong = "animation_too_long" // 422: more frames or seconds than the processor allows
)
View Source
const (
	CodeAnimationUnsupported = "animation_unsupported" // 415: an AVIF/HEIF image sequence (decoded as one frame)
)
View Source
const (
	CodeChecksum = "checksum_mismatch" // 422: stored bytes differ from the declared hash
)
View Source
const (
	CodeConflict = "conflict" // 409: a path taken, or a new item's folder not empty
)
View Source
const (
	CodeForbidden = "forbidden" // 403
)
View Source
const (
	CodeImageTooLarge = "image_too_large" // 413: more pixels than the processor decodes
)
View Source
const (
	// Image refusals (ImageError): the rules refuse the image; never a server fault.
	CodeImageTooSmall = "image_too_small" // 422: edited narrower than the public preset's MinWidth
)
View Source
const (
	CodeImageUnreadable = "image_unreadable" // 422: not a decodable image of its declared type
)
View Source
const (
	CodeIncomplete = "incomplete" // 409: multipart parts missing
)
View Source
const (
	CodeInvalid = "invalid_request" // 400
)
View Source
const (
	CodeNotFound = "not_found" // 404: unknown kind, file or upload
)
View Source
const (
	CodeNotUploaded = "not_uploaded" // 409: commit before the object landed
)
View Source
const (
	CodeQuota = "quota_exceeded" // 413: owner quota
)
View Source
const (
	CodeRate = "rate_limited" // 429
)
View Source
const (
	CodeTooLarge = "too_large" // 413: over the Upload's MaxBytes
)
View Source
const (
	CodeTooManyFiles = "too_many_files" // 409: the commit would exceed an Upload's Max
)
View Source
const (
	CodeType = "type_not_allowed" // 415
)
View Source
const (
	CodeUnavailable = "unavailable" // 503: the bucket cannot be reached; retry
)
View Source
const (
	CodeUpgrade = "upgrade_required" // 503: the item's publication is being restored
)
View Source
const (
	// CodeVideoAspectUnsupported: the display aspect is outside its HLS
	// presets' MinAspect and MaxAspect.
	CodeVideoAspectUnsupported = "video_aspect_unsupported" // 422
)
View Source
const (
	CodeVideoOverBudget = "video_over_budget" // 422: the planned encode is over MaxWork, or the source averages under a frame a second
)
View Source
const (
	CodeVideoTooLarge = "video_too_large" // 422: frames larger than MaxPixels
)
View Source
const (
	// Video refusals (ImageError, recorded as the upload's Failure): its
	// Upload.Video limits refuse what the real stream would cost.
	CodeVideoTooLong = "video_too_long" // 422: runs longer than MaxSeconds (audio too)
)
View Source
const CookieName = token.CookieName

CookieName is the media gateway's cookie.

View Source
const CoverPreset = "cover"

CoverPreset is the public preset a content's or a group's cover shows.

View Source
const (
	DefaultMaxAspect = 2.4
)
View Source
const (
	DefaultMinAspect = 1 / 2.4
)
View Source
const (
	EventProcessingCompleted = "media.processing_completed"
)
View Source
const (
	EventProcessingProgressed = "media.processing_progressed"
)
View Source
const (
	HLSContentType = "application/vnd.apple.mpegurl"
)
View Source
const ItemProgressKey = ""

ItemProgressKey carries Item in a job's reported map.

View Source
const ManifestVersion = 3

ManifestVersion is the manifest format.

View Source
const (
	MaxAudioTracks = 8
)
View Source
const (
	MaxItemMetaBytes = 16 << 10 // the item's meta, as JSON
)
View Source
const (
	MaxManifestBytes = 8 << 20
)
View Source
const (
	MaxMetaBytes = 4 << 10 // an upload's meta, as JSON
)
View Source
const (
	MaxPartSize = 16 << 20
)
View Source
const (
	MaxSinglePut = 64 << 20
)
View Source
const (
	MaxSubtitleTracks = 16
)
View Source
const (
	MaxUploads = 10000
)
View Source
const (
	MetaAutoCover = "auto_cover" // automatic cover ownership; explicit uploads clear it
)
View Source
const (
	MetaCharset = "charset" // a subtitle's IANA charset, overriding detection
)
View Source
const (
	MetaFor = "for" // a subtitle's video upload path; default every video of the item
)
View Source
const (
	MetaForced = "forced" // bool: a forced-narrative subtitle track
)
View Source
const (
	MetaLabel = "label" // a track's name
)
View Source
const (
	MetaLang = "lang" // subtitles and audio: BCP 47
)
View Source
const (
	MinPartSize = 8 << 20
)
View Source
const NamedPrefix = "i-"

NamedPrefix starts the names the server gives Named uploads.

View Source
const (
	OpAttach = "attach" // make an unattached upload part of the item
)
View Source
const (
	OpCopy = "copy" // copy an upload within the kind (CopyFrom), optionally with a new edit
)
View Source
const (
	OpEdit = "edit" // crop and rotate an image upload; nil clears
)
View Source
const (
	OpFrame = "frame" // fill an upload from a frame of its Upload.Frames video, or of another item's (From)
)
View Source
const (
	OpMeta = "meta" // set the template values (download names)
)
View Source
const (
	OpMove = "move" // reorder an upload among its Upload's; its outputs follow
)
View Source
const (
	OpPut = "put" // add an upload, or replace the one with the same path stem
)
View Source
const (
	OpRegenerate = "regenerate" // redo stale outputs and retry failed uploads (of Preset), or every output with Force
)
View Source
const (
	OpRemove = "remove" // remove an upload and its outputs
)
View Source
const (
	OpRename = "rename" // rename an upload and its outputs
)
View Source
const PageAnalysisRecipe = "page-analysis-v1"

PageAnalysisRecipe versions the evidence independently of image renditions.

View Source
const (
	PhaseDownloading = "downloading" // fetching the original
)
View Source
const (
	PhaseEncoding = "encoding" // the single ffmpeg pass: ladder, audio, subtitles, sprite
)
View Source
const (
	PhaseImages = "images" // item-wide, after every file: poster frame from the renditions
)
View Source
const (
	PhaseMuxing = "muxing" // per-quality MP4 downloads
)
View Source
const (
	PhaseProbing = "probing"
)
View Source
const (
	PhasePublishing = "publishing" // the manifest edit
)
View Source
const (
	PhaseQueued = "queued"
)
View Source
const (
	PhaseUploading = "uploading"
)
View Source
const PublicationLayoutVersion = 1

PublicationLayoutVersion marks explicit separation of retained sources, prepared files and served files in a version-owned item.

View Source
const StartRung = 1080

StartRung is the short side of the variant listed first in each codec: native HLS players (Safari, iOS) start there before measuring.

View Source
const (
	StateFailed = "failed"
)
View Source
const (
	StateFull = "full" // the manifest is Full: work is left, stopped until a commit shrinks it
)
View Source
const (
	StateProcessing = "processing"
)
View Source
const (
	StateReady = "ready"
)
View Source
const (
	TrackAudio = "audio"
)
View Source
const (
	TrackSprite = "sprite"
)
View Source
const (
	TrackSubs = "subs"
)
View Source
const (
	TrackVideo = "video"
)
View Source
const (
	VTTContentType = "text/vtt; charset=utf-8"
)
View Source
const (
	VideoAnimation = "animation"
)
View Source
const (
	VideoLive = ""
)
View Source
const ZipRecipe = "zip-source-names-2"

ZipRecipe versions the Zip producer.

Variables

View Source
var (
	AspectNative = Aspect{}
)
View Source
var DefaultEditor = Image{Width: 2048, Height: 2048, Quality: 82}

DefaultEditor renders editor views.

View Source
var DefaultLadder = []int{2160, 1080, 480}

DefaultLadder is the HLS ladder by short side.

View Source
var DefaultVideoLimits = VideoLimits{MaxSeconds: 4 * 3600, MaxFPS: 60, MaxPixels: 8192 * 4320, MaxWork: 4e13}

DefaultVideoLimits are an upload's VideoLimits where it sets none: 4 h at up to 60 fps, frames up to DCI 8K (8192×4320; the ladder scales larger sources down to 4K), and the work of a 4 h 4K60 default ladder (2160, 1080, 480) in three codecs plus MP4 downloads, about 3e13 pixel-frames.

EncodePhases lists every phase in order.

View Source
var ErrFolderNotEmpty = errors.New("media: new item's folder is not empty")

ErrFolderNotEmpty: a new item's folder already holds objects. Item ids are never reused, so leftovers mean a host bug (a reset id, a restored database); they are never adopted. Purge them deliberately with Jobs.Purge.

View Source
var ErrRateLimited = errors.New("media: rate limited")

ErrRateLimited is a refusal that a later attempt will pass.

View Source
var (
	// ErrUnavailable marks a store that could not be reached or answered 5xx;
	// HTTP handlers answer 503.
	ErrUnavailable = errors.New("media: store unavailable")
)
View Source
var ImageTypes = []string{"image/jpeg", "image/png", "image/webp", "image/gif", "image/avif", "image/heic", "image/heif", "image/tiff"}

ImageTypes are the image types the image presets decode (media/image); an upload feeding one accepts no other. SVG, BMP and JPEG XL are refused: their libvips loaders are blocked as untrusted.

View Source
var (
	Square = Aspect{1, 1}
)

Functions

func PageIncluded added in v0.99.0

func PageIncluded(f File) bool

PageIncluded is the planner's persisted effective selection. An ordinary upload or an older page without a decision remains included.

func ValidNamed added in v0.62.0

func ValidNamed(name string) bool

ValidNamed reports a server-given name ("i-{uuid}").

Types

type Animation added in v0.39.0

type Animation string

Animation is a policy for animated images (GIF, WebP; AVIF/HEIF sequences are refused as animation_unsupported, never flattened).

const (
	// AnimationAllow keeps every frame, delay and the loop count.
	AnimationAllow Animation = ""
)
const (
	// AnimationReject refuses an animated upload with animation_not_allowed.
	AnimationReject Animation = "reject"
)

type ArchiveStatus added in v0.125.0

type ArchiveStatus struct {
	ProcessingCount
	Pages *ProcessingCount `json:"pages,omitempty"`
}

ArchiveStatus counts source ZIPs and, once validation has determined the expected entries, the pages actually committed by the ingest worker. Page counts are persisted progress, not a claim that a worker is running.

type Aspect added in v0.40.0

type Aspect struct{ W, H int }

Aspect is a width:height ratio in lowest terms, written "W:H" ("3:1", "9:16"). The zero value is AspectNative: the source's own shape.

func ParseAspect added in v0.40.0

func ParseAspect(s string) (Aspect, error)

ParseAspect parses "W:H" with positive integer terms up to 10000 and reduces it ("6:2" is "3:1"); "" and "native" are AspectNative.

func Ratio added in v0.40.0

func Ratio(s string) Aspect

Ratio parses "W:H" and panics on an invalid one (for constants in code).

func (Aspect) Height added in v0.40.0

func (a Aspect) Height(width int) int

Height is width's height at a, rounded half up, at least 1 (0 when native).

func (Aspect) MarshalText added in v0.40.0

func (a Aspect) MarshalText() ([]byte, error)

MarshalText writes "W:H" (native: empty), so JSON and config carry the string.

func (Aspect) Native added in v0.40.0

func (a Aspect) Native() bool

Native reports the source's own shape.

func (Aspect) Rotated added in v0.40.0

func (a Aspect) Rotated() Aspect

Rotated is a turned a quarter (90 or 270 degrees).

func (Aspect) String added in v0.40.0

func (a Aspect) String() string

func (*Aspect) UnmarshalText added in v0.40.0

func (a *Aspect) UnmarshalText(b []byte) error

func (Aspect) Valid added in v0.40.0

func (a Aspect) Valid() bool

Valid reports a native or reduced, bounded ratio.

func (Aspect) Width added in v0.40.0

func (a Aspect) Width(height int) int

Width is height's width at a, rounded half up, at least 1 (0 when native).

type Avatars added in v0.71.0

type Avatars struct {
	Kind   string `json:"kind"`
	Preset string `json:"preset"`
}

Avatars is Config.Avatars: Kind's items are people's accounts, keyed by the host auth's subject (auth.Identity.Subject), such as the shared accounts kind "user", and Preset is the public image each is shown with.

type Capabilities

type Capabilities struct {
	ConditionalPut bool // If-Match / If-None-Match on PUT
	ChecksumSHA256 bool // x-amz-checksum-sha256 enforced on PUT
}

Capabilities are backend features the library depends on, established by Probe.

type Codec added in v0.53.0

type Codec string

Codec is a video codec of an HLS ladder: each rung is encoded in each of the worker's codecs (Track.Codec).

const (
	CodecAV1 Codec = "av1"
)
const (
	CodecH264 Codec = "h264"
)
const (
	CodecHEVC Codec = "hevc"
)

type CommitBody

type CommitBody struct {
	Ref         RefBody `json:"ref"`
	OperationID string  `json:"operation_id"` // stable UUID for this complete ordered batch
	Ops         []Op    `json:"ops"`
}

CommitBody applies ops to an item in one conditional write.

type CommitReceipt added in v0.68.0

type CommitReceipt struct {
	Operation string `json:"operation"`
	Attempt   string `json:"attempt"`
}

CommitReceipt proves which prepared attempt reached S3. Every writer keeps the receipt until recovery has settled it; it is not an authorization token.

type CommitReply

type CommitReply struct {
	Files []FileInfo `json:"files"`
}

CommitReply is the item's uploads as an editor reads them.

type CompleteReply

type CompleteReply struct {
	Blob string `json:"blob"`
	Type string `json:"type"`
	Size int64  `json:"size"`
}

CompleteReply is a completed multipart upload; Blob is its staged name.

type Config added in v0.62.0

type Config struct {
	// Namespace is the app's own namespace, e.g. "doujins": its kinds' items
	// live under {Namespace}/{kind}/{id}/.
	Namespace string `json:"namespace,omitempty"`
	// Scope derives object roots and internal partitions; Namespace is legacy-only.
	Scope layout.Scope `json:"scope,omitzero"`
	// BaseURL is the site's media origin, e.g. "https://media.doujins.ai":
	// every URL is {BaseURL}/v1/{namespace}/{kind}/{id}/{public|private}/{name}.
	BaseURL string `json:"base_url,omitempty"`
	// Kinds are the app's kinds plus the shared kinds it imports.
	Kinds []Kind `json:"kinds"`
	// Avatars names people's avatars: content shows them beside comment
	// authors and in moderation lists. Zero: people have none.
	Avatars Avatars `json:"avatars,omitzero"`
	// Editor is how editor views render (the whole oriented source the
	// cropper draws on); zero is DefaultEditor.
	Editor Image `json:"editor,omitzero"`
}

Config is the app's media registry, as data (NewRegistry).

func ForContent added in v0.81.0

func ForContent(c Config, k kinds.Config) (Config, error)

ForContent derives c from the site's one kinds list: a media kind named after a content kind is that kind's, of Versions, in the app's namespace; every entity kind without one declared gets GroupKind's. No other kind has versions.

func ParseConfig added in v0.62.0

func ParseConfig(b []byte) (Config, error)

ParseConfig reads a registry written by Registry.MarshalJSON; unknown keys are ignored.

type CopyBody added in v0.81.0

type CopyBody struct {
	Ref   RefBody       `json:"ref"`
	Files []CopyRequest `json:"files"`
}

CopyBody stages server-side copies of keys of the item's bucket outside ContentKit's namespaces (an importer's), for one commit's puts.

type CopyFrom added in v0.62.0

type CopyFrom struct {
	Kind    string `json:"kind,omitempty"` // frame only
	ID      string `json:"id"`
	Version string `json:"version,omitempty"`
	Path    string `json:"path"`
}

CopyFrom names an upload of an item of the same kind, including this item: of a versioned kind, one version's. Into a published kind's item, it names a file of a version of the kind it publishes: an upload, or a finished output, which comes alone, as an upload. A frame op's names a video upload of any item in the namespace (Kind, default this item's) the editor may edit; the worker grabs it once.

type CopyOptions added in v0.40.0

type CopyOptions struct {
	IfMatch     string
	ContentType string
	// Metadata merges trusted operation receipts into the copied object's
	// existing metadata as part of the server-side copy itself.
	Metadata map[string]string
}

CopyOptions: IfMatch copies only while the source's ETag is this one (ErrPreconditionFailed otherwise); ContentType replaces the source's.

type CopyReply added in v0.81.0

type CopyReply struct {
	Files []StagedCopy `json:"files"`
}

CopyReply is each copy's path to commit and staged blob, in order.

type CopyRequest added in v0.81.0

type CopyRequest struct {
	Path string `json:"path"`
	Type string `json:"type"`
	From string `json:"from"`
	Size int64  `json:"size,omitempty"` // checked when > 0
}

CopyRequest stages a server-side copy of From, a key of the item's bucket outside ContentKit's namespaces, as an upload at Path.

type Crop added in v0.17.0

type Crop struct {
	X int `json:"x"`
	Y int `json:"y"`
	W int `json:"w"`
	H int `json:"h"`
}

Crop is a rectangle in source pixels.

type Deletion

type Deletion struct {
	Ref         contentref.ContentRef
	Owner       string
	OperationID string // required by Purge with a quota owner; stable across retries
}

Deletion is one item to delete. Owner is its quota owner (UploadGrant.Owner), "" for none; with a Limiter configured the owner's usage is released. OperationID is required for Purge; queued deletion uses its River job id.

type Delivery

type Delivery struct {
	Mode DeliveryMode
	// CookieDomain is the site's registrable domain, e.g. "doujins.ai";
	// required in cookie mode, because a host-only cookie never reaches media.
	CookieDomain string
	// SigningKey is the current key of the ring the media gateway verifies.
	SigningKey token.Key
	// TTL is the minimum token lifetime (default 1h); expiries round up to
	// Window (default token.DefaultWindow, whole seconds).
	TTL, Window time.Duration
}

Delivery is the host's signing configuration; URLs are at the registry's BaseURL.

type DeliveryMode

type DeliveryMode string

DeliveryMode is how viewers with access present their item token.

const (
	// DeliverCookie (default) sets the item cookie; URLs are plain.
	DeliverCookie DeliveryMode = "cookie"
)
const (
	// DeliverURL appends ?t= to every URL: apps and clients without cookies.
	DeliverURL DeliveryMode = "url"
)

type Dims added in v0.17.0

type Dims struct {
	W int `json:"w"`
	H int `json:"h"`
}

Dims is a source's size with EXIF orientation applied.

type DownloadState added in v0.87.0

type DownloadState int

DownloadState is how far an item's Download file is.

const (
	DownloadNone    DownloadState = iota // nothing to serve: no source, a failed or dropped one
	DownloadPending                      // still being placed or produced
	DownloadReady
)

type Edit added in v0.17.0

type Edit struct {
	Crop   *Crop `json:"crop,omitempty"`
	Rotate int   `json:"rotate,omitempty"` // clockwise degrees: 0, 90, 180 or 270
}

Edit is a non-destructive image edit: Crop, in the source's pixels (EXIF orientation applied), then a clockwise Rotate. Variants derive from the source through it; the source is never modified.

func (*Edit) Check added in v0.17.0

func (e *Edit) Check(w, h int) error

Check validates the edit's shape and, with a known size (w, h > 0), that the crop lies inside it.

func (*Edit) Hash added in v0.17.0

func (e *Edit) Hash() string

Hash is the edit's stable identity; "" for no edit.

func (*Edit) Normalize added in v0.17.0

func (e *Edit) Normalize() *Edit

Normalize returns nil for an identity edit, else a copy.

func (*Edit) Size added in v0.17.0

func (e *Edit) Size(w, h int) (int, int)

Size is the edited size of a w×h source.

type EditorImage added in v0.68.0

type EditorImage struct {
	Blob string `json:"blob"`
	FP   string `json:"fp"`
}

EditorImage records the rendered view's allocation and source/spec fingerprint.

type EncodeProgress added in v0.29.0

type EncodeProgress struct {
	Phase         string  `json:"phase"`
	QueuePosition int     `json:"queue_position,omitempty"` // 1 = next; 0 = unknown or behind a file of the same job
	SegmentsDone  int     `json:"segments_done,omitempty"`
	SegmentsTotal int     `json:"segments_total,omitempty"`
	Percent       float64 `json:"percent"`
	Speed         float64 `json:"speed,omitempty"`
	ETA           float64 `json:"eta,omitempty"`
	At            int64   `json:"at"` // unix milliseconds of the measurement
	Stalled       bool    `json:"stalled,omitempty"`
	// Stage of Stages: each rung is published before the next one starts.
	Stage  int `json:"stage,omitempty"`
	Stages int `json:"stages,omitempty"`
}

EncodeProgress is a pending video file's live encode state. Segments count HLS segments of the source's duration; Speed is the encode's smoothed ×realtime; ETA is seconds from At to publish, including uploads. Percent never decreases within a run. Stalled marks a report older than a minute from a running job (a dead worker until River rescues the job).

type EncodeStatus added in v0.29.0

type EncodeStatus struct {
	Files  map[string]EncodeProgress
	Queued *EncodeProgress
	Item   *EncodeProgress
}

EncodeStatus is an item's encode progress: Files from the running job, Queued for pending files it does not cover (a waiting job), Item for the job's item-wide step (PhaseImages).

func (EncodeStatus) Current added in v0.29.0

func (s EncodeStatus) Current() *EncodeProgress

Current is the item's most advanced step: the item-wide one, a running file, else the wait.

type ErrorDetails added in v0.38.0

type ErrorDetails struct {
	Width      int      `json:"width,omitempty"`       // image_too_small: the edited width; image_too_large, video_too_large, video_aspect_unsupported: the source's
	Height     int      `json:"height,omitempty"`      // image_too_large, video_too_large, video_aspect_unsupported: the source's
	MinWidth   int      `json:"min_width,omitempty"`   // image_too_small
	MaxPixels  int      `json:"max_pixels,omitempty"`  // image_too_large, video_too_large
	Type       string   `json:"type,omitempty"`        // the declared type (image_unreadable, type_not_allowed, too_large)
	Allowed    []string `json:"allowed,omitempty"`     // type_not_allowed: the kind's types
	Size       int64    `json:"size,omitempty"`        // too_large: bytes
	MaxBytes   int64    `json:"max_bytes,omitempty"`   // too_large
	Frames     int      `json:"frames,omitempty"`      // animation_too_long, image_too_large: the animation's
	MaxFrames  int      `json:"max_frames,omitempty"`  // animation_too_long
	Seconds    float64  `json:"seconds,omitempty"`     // animation_too_long, video_too_long: running time
	MaxSeconds float64  `json:"max_seconds,omitempty"` // animation_too_long, video_too_long
	MinAspect  float64  `json:"min_aspect,omitempty"`  // video_aspect_unsupported: the narrowest width/height accepted
	MaxAspect  float64  `json:"max_aspect,omitempty"`  // video_aspect_unsupported: the widest width/height accepted
	Max        int      `json:"max,omitempty"`         // too_many_files: the files allowed; comment_too_long: the characters allowed
}

ErrorDetails qualifies an image refusal so clients can state the rule.

type ErrorReply

type ErrorReply struct {
	Error      string        `json:"error"`
	Code       string        `json:"code"`
	RetryAfter int           `json:"retry_after,omitempty"` // seconds, with 429
	Blobs      []string      `json:"blobs,omitempty"`       // not_uploaded at commit: the blobs to upload again
	Details    *ErrorDetails `json:"details,omitempty"`     // image refusals
}

ErrorReply is the error body; Code is one of the Code* constants, "unauthorized" or "internal_error".

type Failure added in v0.62.0

type Failure struct {
	Of      string        `json:"of"` // File.Key it was recorded for
	Message string        `json:"message"`
	Code    string        `json:"code,omitempty"` // an ImageError's code
	Details *ErrorDetails `json:"details,omitempty"`
}

Failure is why an upload's blob through its edit cannot be processed.

type File

type File struct {
	Path string  `json:"path"`           // app path: "originals/001.png", "low-res/001.webp"
	Blob string  `json:"blob,omitempty"` // "sha256-{hex}-{uuid}" in private/; "" for a staged upload or a frame not grabbed yet
	Type string  `json:"type"`
	Size int64   `json:"size,omitempty"`
	W    int     `json:"w,omitempty"` // an upload's oriented size once measured; an output's size
	H    int     `json:"h,omitempty"`
	Dur  float64 `json:"dur,omitempty"`

	// Uploads:
	Admission  *SourceAdmission `json:"admission,omitempty"`  // verified ZIP source quota policy, never client-supplied
	Staged     string           `json:"staged,omitempty"`     // "u-{uuid}" in temp/ until the worker hashes and places it at Blob
	CreateID   string           `json:"create_id,omitempty"`  // create-only put receipt; retained through placement and processing
	Edit       *Edit            `json:"edit,omitempty"`       // crop and rotate in source pixels
	Frame      *Frame           `json:"frame,omitempty"`      // grabbed from a video (the frame op)
	Meta       map[string]any   `json:"meta,omitempty"`       // lang, label, …
	Unattached bool             `json:"unattached,omitempty"` // processed on upload, not yet part of the item
	Gone       bool             `json:"gone,omitempty"`       // blob dropped (KeepOriginals false); the hash stays for provenance
	Pending    []string         `json:"pending,omitempty"`    // presets still producing from this upload
	Failed     *Failure         `json:"failed,omitempty"`     // this blob and edit cannot be processed
	Public     []Publication    `json:"public,omitempty"`     // reserved or published public generations
	Editor     *EditorImage     `json:"editor,omitempty"`     // selected immutable editor view, never listed to ordinary readers

	// Derived files:
	From     string `json:"from,omitempty"`     // the upload's path, or a zip's prefix
	Preset   string `json:"preset,omitempty"`   // the Private preset
	FP       string `json:"fp,omitempty"`       // Fingerprint of its inputs
	Download string `json:"download,omitempty"` // the human download name
	Track    *Track `json:"track,omitempty"`    // HLS
}

File is one file: an upload (no Preset) or a derived file.

func (File) Current added in v0.69.0

func (f File) Current(preset string) (Publication, bool)

Current returns the upload's ready generation of preset.

func (File) Fail added in v0.62.0

func (f File) Fail() *Failure

Fail is the upload's failure for its current blob and edit, or nil.

func (File) HasPageAnalysis added in v0.99.0

func (f File) HasPageAnalysis(recipe string) bool

func (File) IsUpload added in v0.62.0

func (f File) IsUpload() bool

IsUpload reports an upload (a file with no preset).

func (File) Key added in v0.62.0

func (f File) Key() string

Key identifies the source and edit an upload's Failure applies to.

func (File) Publication added in v0.68.0

func (f File) Publication(preset string) (Publication, bool)

Publication returns the upload's latest generation of preset: its reserved successor if any, else its current one.

func (File) Source

func (f File) Source() string

Source is the object holding an upload's bytes: its blob, or its staged upload until placed.

type FileInfo

type FileInfo struct {
	Path     string  `json:"path"`
	Type     string  `json:"type"`
	Size     int64   `json:"size,omitempty"`
	W        int     `json:"w,omitempty"`
	H        int     `json:"h,omitempty"`
	Dur      float64 `json:"dur,omitempty"`
	Download string  `json:"download,omitempty"` // the name a download read serves it under
	URL      string  `json:"url,omitempty"`

	// Editors (editor reads and commit replies):
	PageID     string          `json:"page_id,omitempty"` // original page bytes' SHA-256, not filename, position or rendition hash
	CreateID   string          `json:"create_id,omitempty"`
	Upload     bool            `json:"upload,omitempty"`
	Staged     bool            `json:"staged,omitempty"` // uploaded, not yet placed by the worker: no blob, views or frames yet
	From       string          `json:"from,omitempty"`
	Edit       *Edit           `json:"edit,omitempty"`
	Frame      *Frame          `json:"frame,omitempty"`
	Meta       map[string]any  `json:"meta,omitempty"`
	Unattached bool            `json:"unattached,omitempty"`
	Pending    []string        `json:"pending,omitempty"`
	Failed     *Failure        `json:"failed,omitempty"`
	EditorURL  string          `json:"editor_url,omitempty"`
	Progress   *EncodeProgress `json:"progress,omitempty"`
}

FileInfo is one file of a read.

type FitMode added in v0.62.0

type FitMode string

FitMode is how an image fits its Width×Height box.

const (
	FitCover FitMode = "cover"
)
const (
	FitInside FitMode = "" // within the box, keeping the aspect
)

type FolderNotEmptyError added in v0.45.0

type FolderNotEmptyError struct {
	Prefix string
	Keys   []string
}

FolderNotEmptyError names the folder and a few of its keys.

func (*FolderNotEmptyError) Error added in v0.45.0

func (e *FolderNotEmptyError) Error() string

func (*FolderNotEmptyError) Unwrap added in v0.45.0

func (e *FolderNotEmptyError) Unwrap() error

type Frame added in v0.62.0

type Frame struct {
	T    float64   `json:"t,omitempty"`
	Auto bool      `json:"auto,omitempty"`
	Of   string    `json:"of,omitempty"`
	From *CopyFrom `json:"from,omitempty"`
}

Frame is an upload grabbed from a frame of its Upload.Frames video: the one a player shows T seconds in; Auto lets the worker choose T. Of is the video blob it was grabbed from: a new video grabs again. From names another item's video instead (Kind always set): grabbed once, it is a still that video's changes leave alone.

type GatewayRules added in v0.65.0

type GatewayRules struct {
	Namespaces []string
	// Scopes are the exact scoped roots; build gateway.Routes for these.
	Scopes   []layout.Scope
	Defaults []layout.Default
}

GatewayRules are the media gateway's rules for an app's media host: the namespaces it serves there (MEDIA_GATEWAY_HOSTS, with layout.FormatHosts; each one's bucket in MEDIA_GATEWAY_BUCKETS) and the default public names of its kinds (MEDIA_GATEWAY_DEFAULTS, with layout.FormatDefaults).

type GetOptions

type GetOptions struct {
	IfNoneMatch string
	Range       string
}

GetOptions: IfNoneMatch returns ErrNotModified on a match; Range is an HTTP Range value.

type HLS

type HLS struct {
	// Ladder is the rendition short sides, largest first; empty is DefaultLadder.
	Ladder []int `json:"ladder,omitempty"`
	// MinAspect and MaxAspect bound the source's display width/height; zero
	// is DefaultMinAspect and DefaultMaxAspect. A source outside fails.
	MinAspect float64 `json:"min_aspect,omitempty"`
	MaxAspect float64 `json:"max_aspect,omitempty"`
	Profile   string  `json:"profile,omitempty"` // VideoLive or VideoAnimation
}

HLS is a byte-range fMP4 ladder, one blob per rendition, with the source's audio and subtitle tracks and a seek sprite. A rung above the source is not produced.

func (*HLS) Aspects added in v0.62.0

func (h *HLS) Aspects() (lo, hi float64)

Aspects are the aspect bounds in effect.

func (*HLS) Rungs added in v0.62.0

func (h *HLS) Rungs() []int

Rungs is the ladder in effect.

type Image added in v0.62.0

type Image struct {
	Format  ImageFormat `json:"format,omitempty"`
	Width   int         `json:"width,omitempty"`
	Height  int         `json:"height,omitempty"`
	Fit     FitMode     `json:"fit,omitempty"`
	Quality int         `json:"quality,omitempty"` // default 80
	Blur    float64     `json:"blur,omitempty"`
	// Aspect and MinWidth bound an upload's edit when this is its public
	// preset's image: the crop is fitted to Aspect, and an edit narrower
	// than MinWidth fails.
	Aspect    Aspect    `json:"aspect,omitzero"`
	MinWidth  int       `json:"min_width,omitempty"`
	Animation Animation `json:"animation,omitempty"`
}

Image is a rendering, WebP by default. Source-format private presets retain the upload's codec and copy unchanged bytes when no resize/edit is needed. Resizing and editing in source format support JPEG, PNG, WebP and GIF. Zero Width and Height keep the full size; nothing is upscaled.

func Fit

func Fit(n int) *Image

Fit is an image within an n×n box.

func (Image) Resolve added in v0.62.0

func (im Image) Resolve(e *Edit, w, h int) (*Edit, error)

Resolve is the edit im applies to a w×h source (EXIF-oriented): e with its crop height fitted to Aspect, or without a crop the largest centred one at Aspect (a native aspect: the whole source). It must lie inside the source and be at least MinWidth wide once edited.

type ImageError added in v0.38.0

type ImageError struct {
	Code    string
	Message string
	Details ErrorDetails
}

ImageError is an image the rules refuse, synchronously (an edit checked against known dims) or in the image job (recorded as the upload's Failure).

func (*ImageError) Error added in v0.38.0

func (e *ImageError) Error() string

type ImageFormat added in v0.102.0

type ImageFormat string

ImageFormat selects WebP encoding or the upload's original codec.

const (
	// ImageFormatSource preserves the upload's codec in a private preset.
	ImageFormatSource ImageFormat = "source"
)
const (
	// ImageFormatWebP is the default for all images and the only format for
	// public presets and editor previews.
	ImageFormatWebP ImageFormat = ""
)

type ImageQuery added in v0.69.0

type ImageQuery struct {
	Ref    contentref.ContentRef
	Preset string
	Name   string
}

ImageQuery selects an item's current public images: all of them, or only those of a Preset, of an upload Name (its path's {name}, e.g. an inline image's "i-{uuid}"), or both.

type Kind

type Kind struct {
	Name string `json:"name"`
	// Namespace is "" for Config.Namespace, or a shared one such as
	// "accounts" whose items every app importing the kind serves.
	Namespace string `json:"namespace,omitempty"`
	// Account places this kind in the tenant account root of a scoped registry.
	Account bool `json:"account,omitempty"`
	// Versions marks a content kind (ForContent). Each version owns its
	// folder; its parent content exists in the catalog, not in storage.
	Versions bool `json:"versions,omitempty"`
	// Publish describes the existing files a version's reader can use.
	// Published snapshots contain metadata, not separate media folders.
	Publish *Publish `json:"publish,omitempty"`
	Uploads []Upload `json:"uploads"`
	// KeepOriginals keeps an upload's blob once its private outputs exist;
	// version-owned content always retains its originals independently of this flag.
	// otherwise it is dropped (File.Gone). Public presets' sources are
	// always kept, so unhiding can render them again, as are body images,
	// which new versions copy.
	KeepOriginals bool `json:"keep_originals,omitempty"`
	// ServeOriginals lists and serves uploads to viewers with access, like
	// any private file. Otherwise viewer URLs are scoped to served files,
	// not the whole private folder, and reads omit upload paths and blobs.
	ServeOriginals bool `json:"serve_originals,omitempty"`
	// Downloads are the upload paths and private presets (Image, MP4 or Zip)
	// whose files live in download/: only a download token opens them and
	// reads never list them. ForContent adds a content kind's originals, its
	// zip and what the zip packs.
	Downloads []string `json:"downloads,omitempty"`
	// Download is what a version's download serves, one of Downloads: a
	// literal upload (the original) or an MP4 or Zip preset. ForContent sets
	// it from the content kind's download; "" serves none.
	Download string    `json:"download,omitempty"`
	Private  []Private `json:"private,omitempty"`
	Public   []Public  `json:"public,omitempty"`
	// Defaults holds the images the kind's public presets name in
	// Public.Default, so a shared kind ships its own (go:embed). A registry
	// read from JSON (the stock worker) has none; PublishDefaults needs them.
	Defaults fs.FS `json:"-"`
}

Kind declares one kind of item: what may be uploaded, what is derived from the uploads in private/, and which public images it has. NewRegistry validates it into a RegisteredKind.

func EntityKind added in v0.117.0

func EntityKind(name string, gk kinds.EntityKind) Kind

GroupKind is a entity kind's media: named cover images ("cover/i-{uuid}"), and for kinds with avatars (kinds.GroupKind.HasAvatar) named avatars, each the group's selection (entities.Cover.Image) among them.

type LimitError added in v0.62.0

type LimitError struct{ RetryAfter time.Duration }

LimitError is ErrRateLimited with how long to wait.

func (*LimitError) Error added in v0.62.0

func (e *LimitError) Error() string

func (*LimitError) Is added in v0.62.0

func (e *LimitError) Is(target error) bool

type MP4 added in v0.62.0

type MP4 struct {
	Rung    int    `json:"rung"`
	Profile string `json:"profile,omitempty"`
}

MP4 is a muxed H.264 MP4 at one rung (short side), with the default audio.

func Rung added in v0.62.0

func Rung(n int) *MP4

Rung is an MP4 at short side n.

type MediaStatus added in v0.125.0

type MediaStatus struct {
	State        string              `json:"state"`
	Uploads      ProcessingCount     `json:"uploads"`
	Archives     ArchiveStatus       `json:"archives"`
	Presets      []PresetStatus      `json:"presets"`
	Encoding     *EncodeProgress     `json:"encoding,omitempty"`
	FailureCount int                 `json:"failure_count"`
	Failures     []ProcessingFailure `json:"failures"`
}

MediaStatus is a read-only editor snapshot of all uploads, including staging. Unattached sources count placement and private processing; their public presets wait until attachment. This state is separate from publication readiness. Public presets count after attachment. An archive may have finished placement while still waiting for extraction. Encoding is the existing worker checkpoint, when available, never a new job or operation.

type Multipart

type Multipart struct {
	Ticket      string
	MinPartSize int64
	MaxPartSize int64
	MaxParts    int
}

Multipart carries the opaque ticket for PresignParts, ListParts, Complete and Abort, and the part-size bounds the client adapts within.

type MultipartReply

type MultipartReply struct {
	Ticket      string `json:"ticket"`
	MinPartSize int64  `json:"min_part_size"`
	MaxPartSize int64  `json:"max_part_size"`
	MaxParts    int    `json:"max_parts"`
}

type Object

type Object struct {
	Key            string
	Size           int64
	ETag           string
	ContentType    string
	CacheControl   string
	ContentRange   string
	LastModified   time.Time
	ChecksumSHA256 []byte            // set when the backend stored a full-object SHA-256
	Metadata       map[string]string // user metadata (x-amz-meta-*), lower-case keys; Head and Get
}

Object is object metadata. For a ranged Get, Size is the body length and ContentRange is set.

type ObjectVersion added in v0.68.0

type ObjectVersion struct {
	Key, VersionID string
}

ObjectVersion identifies immutable bytes in a versioned bucket.

type Op

type Op struct {
	Op         string         `json:"op"`
	SourceName string         `json:"source_name,omitempty"`
	Path       string         `json:"path,omitempty"`
	Blob       string         `json:"blob,omitempty"`      // put: the staged upload (u-{uuid}) or a blob in the folder
	CreateID   string         `json:"create_id,omitempty"` // put: create-only UUID; repeat the same ID to retry
	Replace    bool           `json:"replace,omitempty"`   // put: explicitly replace the target, including another source alias
	Index      *int           `json:"index,omitempty"`     // put, move, attach: among the attached uploads of its Upload
	Meta       map[string]any `json:"meta,omitempty"`      // put, copy: upload meta; attach: merged; meta: item meta; remove: auto_cover guards ownership
	Edit       *Edit          `json:"edit,omitempty"`      // put, edit, copy, frame
	Unattached bool           `json:"unattached,omitempty"`
	To         string         `json:"to,omitempty"`   // rename, copy (default the source's path)
	From       *CopyFrom      `json:"from,omitempty"` // copy; frame: the video
	T          *float64       `json:"t,omitempty"`    // frame: the one a player shows t seconds in
	Auto       bool           `json:"auto,omitempty"` // frame: the worker chooses
	Preset     string         `json:"preset,omitempty"`
	Force      bool           `json:"force,omitempty"`
	// Takedown (remove) also removes the frames grabbed from the upload and
	// the zips that bundled it, then deletes at once, not a grace period
	// later, the blobs the commit dropped, the removed uploads' editor views
	// and the public files no upload renders. With an exempt grant it deletes
	// every private blob the item no longer references (earlier versions and
	// every editor view too), and repeating it, the path already gone, runs
	// that sweep again: how staff complete a takedown that failed part way.
	Takedown bool `json:"takedown,omitempty"`
}

Op is one commit op.

type PageAnalysis added in v0.99.0

type PageAnalysis struct {
	Recipe        string              `json:"recipe"`
	SourceSHA256  string              `json:"source_sha256"`
	Status        string              `json:"status"` // complete | unsupported | failed
	Width         int                 `json:"width,omitempty"`
	Height        int                 `json:"height,omitempty"`
	Frames        int                 `json:"frames,omitempty"`
	PixelSHA256   string              `json:"pixel_sha256,omitempty"`
	PixelFormat   string              `json:"pixel_format,omitempty"`
	ProfileSHA256 string              `json:"profile_sha256,omitempty"`
	Blank         string              `json:"blank"` // none | blank | suspected | unknown
	BlankReason   string              `json:"blank_reason,omitempty"`
	Confidence    string              `json:"confidence"` // exact | high | possible | unknown
	Metrics       PageAnalysisMetrics `json:"metrics,omitzero"`
	Flags         []string            `json:"flags,omitempty"`
}

PageAnalysis is immutable evidence, not the reader's include/exclude decision. The planner owns duplicate keepers, ordering and manual overrides.

func ReadPageAnalysis added in v0.99.0

func ReadPageAnalysis(meta map[string]any) (PageAnalysis, bool)

ReadPageAnalysis accepts both newly typed values and JSON-decoded metadata.

type PageAnalysisMetrics added in v0.99.0

type PageAnalysisMetrics struct {
	Pixels           uint64   `json:"pixels"`
	VisiblePixels    uint64   `json:"visible_pixels"`
	OpaquePixels     uint64   `json:"opaque_pixels"`
	ForegroundPixels uint64   `json:"foreground_pixels"`
	MinRGB           [3]uint8 `json:"min_rgb"`
	MaxRGB           [3]uint8 `json:"max_rgb"`
}

type Part

type Part struct {
	Number int32
	Size   int64
	ETag   string
	SHA256 []byte
}

Part is one uploaded multipart part.

type PartBody

type PartBody struct {
	Number int32  `json:"number"`
	Size   int64  `json:"size"`
	SHA256 string `json:"sha256"`
}

type PartReply

type PartReply struct {
	Number  int32         `json:"number"`
	Size    int64         `json:"size,omitempty"`
	SHA256  string        `json:"sha256,omitempty"`
	Request *RequestReply `json:"request,omitempty"`
}

PartReply is a presigned part (parts) or a landed part (parts/list).

type PartRequest

type PartRequest struct {
	Number int32
	Size   int64
	SHA256 []byte
}

PartRequest is one part to presign: its exact length and SHA-256.

type PartsBody

type PartsBody struct {
	Ticket string     `json:"ticket"`
	Parts  []PartBody `json:"parts"`
}

type PartsReply

type PartsReply struct {
	Parts []PartReply `json:"parts"`
}

type PresetRule added in v0.68.0

type PresetRule struct {
	Kind      string `json:"kind"`
	Name      string `json:"name"`
	From      string `json:"from"`
	Base      string `json:"base"`
	Namespace string `json:"namespace"`
	// Root is the server-selected path before Kind, including its trailing slash.
	Root   string `json:"root,omitempty"`
	To     string `json:"to"`
	Widths []int  `json:"widths"`
	// Aspect is the rendition's shape ("W:H"); absent keeps the edit's.
	Aspect Aspect `json:"aspect,omitzero"`
	// MinWidth is the narrowest edit the preset accepts.
	MinWidth int `json:"min_width,omitempty"`
	// First makes it a preview: the first First uploads, {n} in To.
	First int `json:"first,omitempty"`
	// Default: the gateway serves the kind's default image at the template's
	// names while an item has no publication (Registry.DefaultImage).
	Default bool `json:"default"`
	// Stable: the template's names are also the current image's
	// (Public.Stable), so clients build its URLs from an item's id.
	Stable bool `json:"stable,omitempty"`
}

PresetRule is a kind's public preset: its upload, name template, widths and crop bounds. Published files carry a generation suffix, so {base}/v1/{namespace}/{kind}/{id}/public/{to} ({w} each of Widths) names the kind's default image (only when Default), never an item's current one: a read's Public lists those.

type PresetStatus added in v0.125.0

type PresetStatus struct {
	Name string `json:"name"`
	ProcessingCount
}

PresetStatus is progress for one configured rendition preset.

type PresignBody

type PresignBody struct {
	Ref    RefBody `json:"ref"`
	Path   string  `json:"path"`
	Type   string  `json:"type"`
	Size   int64   `json:"size"`
	SHA256 string  `json:"sha256"`
}

PresignBody declares one upload: its path, type, size and whole-file SHA-256, which finds an identical blob already in the folder and binds a single PUT's body.

type PresignPut

type PresignPut struct {
	ContentType string
	Size        int64
	SHA256      []byte
	TTL         time.Duration
}

PresignPut binds a direct upload to its exact type, length and SHA-256.

type PresignReply

type PresignReply struct {
	Path            string          `json:"path"`
	SourceName      string          `json:"source_name,omitempty"`
	Blob            string          `json:"blob"`
	Exists          bool            `json:"exists,omitempty"`
	Put             *RequestReply   `json:"put,omitempty"`
	Multipart       *MultipartReply `json:"multipart,omitempty"`
	ProcessOnUpload bool            `json:"process_on_upload,omitempty"`
}

PresignReply is the upload plan: Exists (commit directly), one Put, or a Multipart upload. Path is the path to commit: cleaned, with an extension, and named by the server for a Named upload. Blob is the name to commit: the folder's blob (sha256-{hex}-{uuid}) with Exists, else the staged upload (u-{uuid}) the PUT or parts write, which the worker places.

type PresignRequest

type PresignRequest struct {
	Ref    contentref.ContentRef
	Path   string
	Type   string
	Size   int64
	SHA256 []byte
}

PresignRequest declares one upload; SHA256 is the whole file's: it finds an identical blob already in the folder and binds a single PUT's body.

type Presigned

type Presigned struct {
	Path            string
	SourceName      string
	Blob            string
	Exists          bool
	Put             *PresignedRequest
	Multipart       *Multipart
	ProcessOnUpload bool
}

Presigned is the upload plan: Exists (commit it), a single Put, or a Multipart upload. Path is the path to commit; Blob is the name to commit: the folder's blob when Exists, else the staged upload (u-{uuid}) that the PUT or the parts write.

type PresignedPart

type PresignedPart struct {
	Number int32
	PresignedRequest
}

PresignedPart is a part URL.

type PresignedRequest

type PresignedRequest struct {
	Method  string
	URL     string
	Header  http.Header
	Expires time.Time
}

PresignedRequest is a request a browser sends as is, with exactly Header.

type Private added in v0.62.0

type Private struct {
	Name string `json:"name"`
	// From is an upload path or pattern; "" for Zip.
	From string `json:"from,omitempty"`
	// To is the output path template: a file ("low-res/{name}.webp",
	// "video/source-1080p.mp4") or, for producers with several outputs, a
	// directory ending in "/" ("hls/"). Source-format
	// images end in {ext}, the upload's extension: "download/{name}{ext}".
	To string `json:"to"`
	// Download is the human name template a download read signs into the
	// URL, filled from the manifest's meta and {name}: "{title}.zip".
	Download string `json:"download,omitempty"`
	// HostOnly leaves this preset out of generic reads and playlists. Version
	// outputs stay in internal and can be served only by the authorized host
	// download transfer. They never share an allocation with ordinary served
	// outputs, because an item token opens every private file in its folder.
	HostOnly  bool       `json:"host_only,omitempty"`
	Image     *Image     `json:"image,omitempty"`
	HLS       *HLS       `json:"hls,omitempty"`
	MP4       *MP4       `json:"mp4,omitempty"`
	Zip       string     `json:"zip,omitempty"` // the files under this prefix, in manifest order: "high/"
	Subtitles *Subtitles `json:"subtitles,omitempty"`
	// Shapes render an Image preset's uploads of another shape: an upload
	// whose oriented size is in one renders its Image, any other (or one not
	// yet measured) renders Image. Shapes never overlap.
	Shapes []Shape `json:"shapes,omitempty"`
}

Private derives files in private/, recorded in the manifest with their provenance (File.From, Preset, FP). Exactly one producer is set.

func (*Private) ImageFor added in v0.133.0

func (p *Private) ImageFor(d Dims) Image

ImageFor is an Image preset's rendering of an upload of size d: its shape's Image, else Image.

type ProcessingCount added in v0.125.0

type ProcessingCount struct {
	Completed int `json:"completed"`
	Total     int `json:"total"`
	Failed    int `json:"failed"`
}

ProcessingCount counts source files, not individual encoded widths or chunks. Completed and Failed are disjoint; the remaining files are still pending.

type ProcessingEvent added in v0.126.1

type ProcessingEvent struct {
	Kind         string          `json:"kind"`
	ContentID    string          `json:"content_id"`
	VersionID    string          `json:"version_id,omitempty"`
	State        string          `json:"state"`
	Uploads      ProcessingCount `json:"uploads"`
	Archives     ArchiveStatus   `json:"archives"`
	Presets      []PresetStatus  `json:"presets"`
	FailureCount int             `json:"failure_count"`
}

ProcessingEvent is a durable observation of media, without delivery URLs or credentials. Completion includes settled failures; State distinguishes them.

type ProcessingFailure added in v0.125.0

type ProcessingFailure struct {
	Path    string `json:"path"`
	Code    string `json:"code"`
	Message string `json:"message"`
}

ProcessingFailure is an editor-visible failure without internal paths, source URLs or the worker's unfiltered error chain.

type Public added in v0.62.0

type Public struct {
	Name   string `json:"name"`
	From   string `json:"from"`
	To     string `json:"to"` // "cover-{w}.webp", "{name}.webp", "preview-{n}.webp"
	First  int    `json:"first,omitempty"`
	Widths []int  `json:"widths,omitempty"`
	Image  Image  `json:"image"`
	// Default is a path in Kind.Defaults, rendered to the kind's _default
	// item at every width (PublishDefaults).
	Default string `json:"default,omitempty"`
	// Stable also keeps the current image at the logical names (To without
	// a generation), overwritten in place: a URL built from the item's id,
	// which the gateway answers with Default while none is current. One
	// image per item: no {name}, no First.
	Stable bool `json:"stable,omitempty"`
}

Public is a fixed public image: {To} with {w} at each of Widths (or one file without Widths), rendered from an upload through its edit, at public/{name}. With Widths, each width is Image at that width: in the shape of its Width×Height box (both or neither), fitted per Fit, else of the edit. It is never in the manifest; the object carries its from and fp as metadata. A missing one is served Default by the media gateway.

First makes it a preview: the first First attached uploads of From (a {name} pattern) in manifest order, {n} in To their position from 1 ("preview-{n}.webp"). Anyone who can see the item sees them; a position is rendered again when another upload takes it, and names past the last upload are deleted. Everything else of the item stays private.

type PublicImage added in v0.68.0

type PublicImage struct {
	From       string            `json:"from"`
	Preset     string            `json:"preset"`
	Renditions []PublicRendition `json:"renditions"`
}

PublicImage is a published public preset for one upload. From is empty for a preset's default image (Registry.DefaultImage).

func (PublicImage) SrcSet added in v0.68.0

func (p PublicImage) SrcSet() string

SrcSet uses published URLs and actual encoded widths, without deriving a filename from the item ID. Duplicate widths (a small source) occur once.

func (PublicImage) URL added in v0.68.0

func (p PublicImage) URL(width int) string

URL picks the narrowest published rendition at least width pixels wide, or the widest when the source is smaller. An unpublished image has no URL.

type PublicRendition added in v0.68.0

type PublicRendition struct {
	URL string `json:"url"`
	W   int    `json:"w"`
	H   int    `json:"h"`
}

PublicRendition carries its physical URL and actual encoded dimensions.

type Publication added in v0.68.0

type Publication struct {
	Preset string `json:"preset"`
	Source string `json:"source"` // the upload's Key
	FP     string `json:"fp"`
	// Stable records whether this generation also owns its logical names.
	// Nil marks historical manifests whose alias policy was not recorded.
	Stable *bool `json:"stable,omitempty"`
	// Generation suffixes every physical name; "" is a legacy publication,
	// files a pre-v0.68 worker wrote at the logical names (always ready).
	Generation string           `json:"generation"`
	Blobs      []string         `json:"blobs,omitempty"` // version preset outputs prepared in internal/, aligned with Names
	Names      []string         `json:"names"`           // logical preset names at this position
	State      PublicationState `json:"state"`
	Dims       []Dims           `json:"dims"`
}

Publication owns one public preset's physical files. Reservation precedes every PUT; State becomes ready only after all renditions have landed. Retired generations are never reused, even when their source bytes are identical. An upload holds at most one ready publication per preset, the current one, and one reserved successor, which replaces it once ready: cleanup never retires the current files while their successor is written.

func (Publication) NamesOnDisk added in v0.68.0

func (p Publication) NamesOnDisk() []string

NamesOnDisk lists the immutable physical names reserved by the publication.

func (Publication) Ready added in v0.68.0

func (p Publication) Ready() bool

type PublicationState added in v0.68.0

type PublicationState uint8

PublicationState has a fixed-width JSON representation: reserving and publishing a replacement must not consume Full manifests' flag headroom.

const (
	PublicationReserved PublicationState = iota
	PublicationReady
)

type Publish added in v0.81.0

type Publish struct {
	// Pages is the {name} upload of the version's ordered pages:
	// "originals/{name}".
	Pages string `json:"pages"`
	// Renditions are the private image presets from Pages a reader reads,
	// the first at reading size: "low", "thumb".
	Renditions []string `json:"renditions"`
	// Previews names a declared public preview preset (First caps the reader
	// preview count). Its uploads render normally; reader plans may also sign
	// existing private renditions under the live access policy.
	Previews string `json:"previews,omitempty"`
	// Playback is the declared {name} audio upload the reader plays unchanged.
	Playback string `json:"playback,omitempty"`
	// Import is the {name} upload of page archives (application/zip),
	// expanded into Pages in name order.
	Import string `json:"import,omitempty"`
	// Download is the HostOnly Zip preset of the version's pages, which a
	// download serves when its content kind serves pages.
	Download string `json:"download,omitempty"`
}

Publish declares which existing version files a reader may consume. Its immutable metadata snapshot contains no chapter folders or duplicated files; chapter boundaries and release dates are evaluated when the reader asks.

type PutOptions

type PutOptions struct {
	ContentType    string
	CacheControl   string
	ChecksumSHA256 []byte
	IfMatch        string
	IfNoneMatch    string
	Metadata       map[string]string
}

PutOptions are conditions and headers for Put. IfNoneMatch "*" creates only.

type ReadOptions

type ReadOptions struct {
	Prefix        string // only files under this path prefix ("low-res/")
	Offset, Limit int    // the range that gets URLs
	// Paths selects at most 64 exact file paths to receive URLs, independent
	// of ordinal position. All allowed metadata remains in manifest order.
	// It cannot be combined with a nonzero Offset or Limit.
	Paths    []string
	Download bool // URLs serve each file as a download under its name
	// Editor adds an editor's uploads with their edit, frame, meta,
	// pending, failure, editor view and retained source URL, unattached ones
	// included. Source URLs are independent of the viewer's ServeOriginals.
	Editor bool
	// Status returns only whole-manifest processing counts, for editors.
	// It issues no URLs or editor-view work and ignores pagination/prefix.
	Status bool
}

ReadOptions select what a read returns.

type ReadResult

type ReadResult struct {
	Access     string `json:"access"`
	Inspection bool   `json:"inspection,omitempty"` // explicit administrative view; playlists must repeat the management-read request
	// Expires is when the item token (the URLs, the cookie) stops working,
	// in unix seconds. A read before then answers the same token, so a
	// client keeps what it has and reads again shortly before.
	Expires int64          `json:"expires"`
	Meta    map[string]any `json:"meta,omitempty"`
	// Previews are the item's public preview images in order (a Public
	// preset with First): every viewer who can see the item gets them.
	Previews []string `json:"previews,omitempty"`
	// Public lists the exact published renditions. Clients must not infer a
	// current cover or avatar's physical filename from the preset template.
	Public []PublicImage `json:"public,omitempty"`
	// Locked: the item holds files this viewer does not open. A viewer is
	// listed only the files it opens, so Total counts those alone.
	Locked bool `json:"locked,omitempty"`
	Total  int  `json:"total"`
	Offset int  `json:"offset"`
	Limit  int  `json:"limit"`
	// HLS lists the item's playable ladders by output directory ("hls/"):
	// play {read API}/{kind}/{id}/hls/{dir}master.m3u8.
	HLS []string `json:"hls,omitempty"`
	// State is the item's readiness (editors).
	State string `json:"state,omitempty"`
	// Status is a whole-manifest processing snapshot for editors only.
	Status *MediaStatus `json:"status,omitempty"`
	// Full (editors): the item's manifest cannot hold more outputs, so
	// processing stopped; remove uploads (any commit that shrinks it) to
	// resume. Uploads left unprocessed stay pending.
	Full bool `json:"full,omitempty"`
	// Uploads (editors) are the kind's upload paths and their rules.
	Uploads []UploadRule `json:"uploads,omitempty"`
	Files   []FileInfo   `json:"files"`
	// Cookie must be set on the response (cookie delivery, with access).
	Cookie *http.Cookie `json:"-"`
}

ReadResult is the read API's answer: the files under the requested prefix in manifest order (Total of them), each with a URL within [offset, offset+limit). Without access it lists none.

type Readiness added in v0.50.0

type Readiness struct {
	State      string   `json:"state"`
	Processing []string `json:"processing,omitempty"`
	Failed     []string `json:"failed,omitempty"`
}

Readiness is whether an item's media is processed: ready when no attached upload is pending (its public presets count only while the item is visible) and every zip packs its inputs; processing while any is; failed once nothing is processing and an upload failed for its current blob and edit; full while work is left on a Full manifest. Processing and Failed name upload paths (and zip outputs).

func (Readiness) Ready added in v0.50.0

func (r Readiness) Ready() bool

type RefBody

type RefBody struct {
	Kind    string `json:"kind"`
	ID      string `json:"id"`
	Version string `json:"version,omitempty"`
}

RefBody names an item of the handler's registry: of a content kind, one version's; of any other kind, Version "".

type RequestReply

type RequestReply struct {
	Method  string            `json:"method"`
	URL     string            `json:"url"`
	Headers map[string]string `json:"headers"`
	Expires time.Time         `json:"expires"`
}

RequestReply is a presigned request: send exactly these headers (the browser adds Content-Length, which is signed too).

type Segment

type Segment struct {
	Offset  int64
	Length  int64
	Seconds float64
}

Segment is one EXT-X-BYTERANGE segment, encoded as [offset, length, seconds].

func (Segment) MarshalJSON

func (s Segment) MarshalJSON() ([]byte, error)

func (*Segment) UnmarshalJSON

func (s *Segment) UnmarshalJSON(b []byte) error

type Shape added in v0.133.0

type Shape struct {
	WiderThan   Aspect `json:"wider_than,omitzero"`
	NoWiderThan Aspect `json:"no_wider_than,omitzero"`
	Image       Image  `json:"image"`
}

Shape is a range of upload aspects (width:height), wider than WiderThan and no wider than NoWiderThan; an unset bound is open. Tall pages (height at least twice the width) are NoWiderThan 1:2; wide ones WiderThan 1:1. Image keeps its preset's Format and Animation.

type SourceAdmission added in v0.126.0

type SourceAdmission struct {
	// Generation is the accepting commit ID. Removing and re-adding a retained
	// ZIP creates fresh work; metadata edits keep the existing generation.
	Generation string `json:"generation"`
	Target     string `json:"target"`
	Accounting bool   `json:"accounting,omitempty"`
	Owner      string `json:"owner,omitempty"`
	Enforce    bool   `json:"enforce,omitempty"`
	Quota      int64  `json:"quota,omitempty"`
}

SourceAdmission records the verified upload policy accepted for a ZIP source. Only server commit code writes it; HTTP operations cannot supply these fields. A background importer uses the same owner and ceiling when attaching decoded originals. Quota <= 0 is unlimited, as in PGLimits.Quota.

type Sprite

type Sprite struct {
	Cols     int     `json:"cols"`
	Rows     int     `json:"rows"`
	W        int     `json:"w"`
	H        int     `json:"h"`
	Interval float64 `json:"interval"`
}

Sprite is a seek-preview grid of Cols×Rows tiles of W×H, one per Interval seconds.

type StagedCopy added in v0.81.0

type StagedCopy struct {
	Path string `json:"path"`
	Blob string `json:"blob"`
	Size int64  `json:"size"`
}

StagedCopy is a staged copy for a commit's put: its path and blob.

type Store

type Store interface {
	Put(ctx context.Context, key string, body io.Reader, size int64, opts PutOptions) (Object, error)
	Get(ctx context.Context, key string, opts GetOptions) (io.ReadCloser, Object, error)
	Head(ctx context.Context, key string) (Object, error)
	Delete(ctx context.Context, key string) error
	List(ctx context.Context, prefix string) iter.Seq2[Object, error]
	// Copy copies src to dst server-side, keeping its content type (unless
	// o.ContentType), cache control and metadata; objects past the backend's single-copy limit
	// (5 GiB on S3) copy in parts. The returned Object has dst's size.
	Copy(ctx context.Context, src, dst string, o CopyOptions) (Object, error)

	PresignPut(ctx context.Context, key string, p PresignPut) (PresignedRequest, error)
	// PresignGet is for a worker reading an original over HTTP ranges. Its URL
	// uses the store's internal endpoint and must not be returned to browsers.
	PresignGet(ctx context.Context, key string, ttl time.Duration) (PresignedRequest, error)
	CreateMultipart(ctx context.Context, key, contentType string) (uploadID string, err error)
	PresignPart(ctx context.Context, key, uploadID string, number int32, size int64, sha256 []byte, ttl time.Duration) (PresignedRequest, error)
	// PutPart uploads one part from the server, bound to its length and SHA-256.
	PutPart(ctx context.Context, key, uploadID string, number int32, body io.Reader, size int64, sha256 []byte) (Part, error)
	ListParts(ctx context.Context, key, uploadID string) ([]Part, error)
	CompleteMultipart(ctx context.Context, key, uploadID string, parts []Part) (Object, error)
	AbortMultipart(ctx context.Context, key, uploadID string) error

	// Capabilities are the backend's, probed on first use when not given; an
	// error (ErrUnavailable) means they are not known yet.
	Capabilities(ctx context.Context) (Capabilities, error)
	// Check reports whether the backend answers, establishing Capabilities
	// while they are unknown.
	Check(ctx context.Context) error
}

Store is the bucket. Item builds keys and enforces ownership. A backend may recognize canonical temporary keys solely to apply storage expiry policy.

type Subtitles added in v0.62.0

type Subtitles struct{}

Subtitles converts SRT, SSA/ASS and WebVTT to clean UTF-8 WebVTT. A video lists the item's converted subtitles as tracks after its own.

type TicketBody

type TicketBody struct {
	Ticket string `json:"ticket"`
}

type Track added in v0.62.0

type Track struct {
	Kind      string `json:"kind"`             // TrackVideo, TrackAudio, TrackSubs, TrackSprite
	Codec     string `json:"codec,omitempty"`  // video: h264, hevc, av1
	Codecs    string `json:"codecs,omitempty"` // RFC 6381
	Bandwidth int    `json:"bw,omitempty"`
	Average   int    `json:"avg,omitempty"`
	ID        string `json:"id,omitempty"`
	Lang      string `json:"lang,omitempty"`
	Label     string `json:"label,omitempty"`
	Default   bool   `json:"default,omitempty"`
	Forced    bool   `json:"forced,omitempty"`
	Index     string `json:"index,omitempty"` // "sha256-{hex}-{uuid}": the TrackIndex
}

Track is an HLS track file. It is small: the segment table or sprite grid is its own private blob, Index (a TrackIndex), cached by hash.

type TrackIndex added in v0.62.0

type TrackIndex struct {
	Segments []Segment `json:"segments,omitempty"`
	Sprite   *Sprite   `json:"sprite,omitempty"`
}

TrackIndex is a Track's index blob: a byte-range track's segments (its init segment is bytes [0, Segments[0].Offset)), or a sprite's grid.

type Upload added in v0.62.0

type Upload struct {
	Path string `json:"path"`
	// ArchiveTo expands a ZIP into this image upload pattern during ingestion.
	// It is media-level policy and may target gallery pages or body images.
	ArchiveTo string `json:"archive_to,omitempty" yaml:"archive_to"`
	// Body marks a content kind's body images (Named, with a private image
	// preset and no public one): each version keeps its copy in private/,
	// which only the version's openers read.
	Body     bool     `json:"body,omitempty"`
	Types    []string `json:"types"`            // accepted content types
	MaxBytes int64    `json:"max_bytes"`        // per file
	Max      int      `json:"max,omitempty"`    // uploads matching Path; 0 is unlimited
	Frames   string   `json:"frames,omitempty"` // may be grabbed from a frame of this video upload (the frame op)
	Named    bool     `json:"named,omitempty"`  // the server names it ({name} is "i-{uuid}"): inline images
	// Video bounds a video upload as probed from its real stream;
	// nil or zero fields take the defaults (DefaultVideoLimits).
	Video *VideoLimits `json:"video,omitempty"`
}

Upload is an app path that may be uploaded: a literal ("cover") or a pattern ending in {name} ("originals/{name}"). A file's path is the path plus its extension ("cover.png", "originals/001.png"); a put to the same stem replaces it.

type UploadAuthorizer

type UploadAuthorizer interface {
	CanUpload(ctx context.Context, actor access.Actor, t UploadTarget) (UploadGrant, error)
}

UploadAuthorizer is the app's upload permission check, run at presign and commit against what is written.

type UploadError

type UploadError struct {
	Code       string
	Message    string
	RetryAfter time.Duration // CodeRate: when the window frees
	Blobs      []string      // CodeNotUploaded at commit: the blobs to upload again
	Details    *ErrorDetails // image refusals
}

UploadError is a refused upload request. UploadLimiter implementations refuse with CodeRate or CodeQuota.

func (*UploadError) Error

func (e *UploadError) Error() string

func (*UploadError) Status

func (e *UploadError) Status() int

Status is the HTTP status for Code.

type UploadGrant

type UploadGrant struct {
	Allowed bool
	Exempt  bool
	Owner   string
	// ArchiveTo explicitly approves every generated filename in this configured
	// destination pattern. Empty does not authorize expansion.
	ArchiveTo string
}

UploadGrant is the app's verdict. Exempt (trusted roles) skips the UploadLimiter; Owner is the quota owner, "" for none.

type UploadRule added in v0.68.0

type UploadRule struct {
	Path     string   `json:"path"`
	Types    []string `json:"types"`
	MaxBytes int64    `json:"max_bytes"`
	// Max caps the files at Path; 0 is unlimited.
	Max   int  `json:"max,omitempty"`
	Named bool `json:"named,omitempty"`
	Page  bool `json:"page,omitempty"` // original pages of a versioned reader
	// Body: the upload holds the body's images (Upload.Body).
	Body   bool   `json:"body,omitempty"`
	Frames string `json:"frames,omitempty"`
	// Aspect and MinWidth bound an image's edit: its first public preset's.
	Aspect   Aspect `json:"aspect,omitzero"`
	MinWidth int    `json:"min_width,omitempty"`
	// Video is a video upload's limits in effect; MinAspect and
	// MaxAspect the display aspects (width/height) its HLS presets accept.
	Video     *VideoLimits `json:"video,omitempty"`
	MinAspect float64      `json:"min_aspect,omitempty"`
	MaxAspect float64      `json:"max_aspect,omitempty"`
}

UploadRule is one upload path's rules, as editor reads carry them so a client turns away a file the server would refuse. The server stays the authority.

type UploadTarget added in v0.60.0

type UploadTarget struct {
	Ref  contentref.ContentRef
	Path string
}

UploadTarget is what an upload writes: an item and an upload path stem ("cover", "originals/001"); "" for ops that change no one upload (move, meta, regenerate).

type VideoJobClass added in v0.58.0

type VideoJobClass string

VideoJobClass selects the priority of a new video run. An empty class is an upload; re-encodes and backfills yield to new playable videos.

const (
	VideoBackfill VideoJobClass = "backfill"
)
const (
	VideoReencode VideoJobClass = "reencode"
)

type VideoLimits added in v0.62.0

type VideoLimits struct {
	MaxSeconds float64 `json:"max_seconds,omitempty"` // real running time
	MaxFPS     float64 `json:"max_fps,omitempty"`     // output frame rate (at most 60); a faster source is encoded at it
	MaxPixels  int     `json:"max_pixels,omitempty"`  // displayed frame area
	// MaxWork bounds the planned encode: the sum over the HLS and MP4
	// presets' rungs and codecs of output pixels × output frames.
	MaxWork float64 `json:"max_work,omitempty"`
}

VideoLimits bound what one video upload may cost the worker; an upload past them fails (video_too_long, video_too_large, video_over_budget) before any encode runs.

func (*VideoLimits) Limits added in v0.62.0

func (l *VideoLimits) Limits() VideoLimits

Limits are the limits in effect: l's, and the defaults for nil or zero fields.

Directories

Path Synopsis
Package avatar provides a user-avatar kind for ContentKit media registries.
Package avatar provides a user-avatar kind for ContentKit media registries.
Package gateway serves the exact app/account roots declared for a media host.
Package gateway serves the exact app/account roots declared for a media host.
Package layout defines media object keys, dependency-free so the media gateway can classify paths without importing the media runtime.
Package layout defines media object keys, dependency-free so the media gateway can classify paths without importing the media runtime.
Package s3 implements media.Store over aws-sdk-go-v2 for Ceph RGW (production) and MinIO (tests).
Package s3 implements media.Store over aws-sdk-go-v2 for Ceph RGW (production) and MinIO (tests).
Package token signs and verifies media access tokens, shared by the host signer and the media gateway so the format cannot drift:
Package token signs and verifies media access tokens, shared by the host signer and the media gateway so the format cannot drift:
Package versions publishes content versions and binds their optional media.
Package versions publishes content versions and binds their optional media.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL