Class: Parse::Embeddings::MediaFile

Inherits:
Object
  • Object
show all
Defined in:
lib/parse/embeddings/media_file.rb

Overview

A file-backed image or video input that is streamed into the request body rather than read into memory.

This is the memory-safe counterpart to ImageFetch::FetchedImage, which holds raw bytes. A MediaFile holds only a path, a sniffed MIME type, and a byte count; the bytes are read and base64-encoded incrementally by StreamingBody while the request is being written to the socket. Peak memory stays at StreamingBody::READ_CHUNK no matter how large the file is, which is what makes video viable on a small dyno.

Only the first 16 bytes are read at construction time, to sniff the container. The Content-Type header and the filename extension are never consulted.

Examples:

stream a local image

img = Parse::Embeddings::MediaFile.image("diagram.png")
provider.embed_image([img])

stream a local video

clip = Parse::Embeddings::MediaFile.video("demo.mp4")
provider.embed_video([clip])

Defined Under Namespace

Classes: TooLarge

Constant Summary collapse

DEFAULT_MAX_MEDIA_BYTES =

Voyage documents 20 MB per image and 20 MB per video. Overridable via Parse::Embeddings.max_media_bytes=.

20 * 1024 * 1024

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(path:, mime_type:, kind:) ⇒ MediaFile

Returns a new instance of MediaFile.



96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/parse/embeddings/media_file.rb', line 96

def initialize(path:, mime_type:, kind:)
  @path = ::File.expand_path(path)
  @mime_type = mime_type
  @kind = kind
  @byte_size = ::File.size(@path)
  if @byte_size.zero?
    raise ArgumentError,
          "Parse::Embeddings::MediaFile: #{path.inspect} is empty."
  end
  cap = Parse::Embeddings.max_media_bytes
  if @byte_size > cap
    raise TooLarge,
          "Parse::Embeddings::MediaFile: #{path.inspect} is #{@byte_size} bytes, over " \
          "the #{cap}-byte limit (Parse::Embeddings.max_media_bytes). Voyage rejects " \
          "media above 20 MB — downscale or re-encode before embedding."
  end
end

Instance Attribute Details

#byte_sizeInteger (readonly)

Returns size in bytes, captured at construction.

Returns:

  • (Integer)

    size in bytes, captured at construction.



42
43
44
# File 'lib/parse/embeddings/media_file.rb', line 42

def byte_size
  @byte_size
end

#kindSymbol (readonly)

Returns :image or :video.

Returns:

  • (Symbol)

    :image or :video.



44
45
46
# File 'lib/parse/embeddings/media_file.rb', line 44

def kind
  @kind
end

#mime_typeString (readonly)

Returns sniffed MIME type.

Returns:

  • (String)

    sniffed MIME type.



40
41
42
# File 'lib/parse/embeddings/media_file.rb', line 40

def mime_type
  @mime_type
end

#pathString (readonly)

Returns absolute path to the backing file.

Returns:

  • (String)

    absolute path to the backing file.



38
39
40
# File 'lib/parse/embeddings/media_file.rb', line 38

def path
  @path
end

Class Method Details

.image(path) ⇒ MediaFile

Wrap a local image file. Verifies the magic bytes against Parse::Embeddings.allowed_image_types.

Parameters:

Returns:

Raises:



53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/parse/embeddings/media_file.rb', line 53

def image(path)
  header = read_header(path)
  mime = ImageFetch.sniff_mime(header)
  if mime.nil?
    raise ImageFetch::InvalidImageType.new(:unknown_magic,
      "Parse::Embeddings::MediaFile.image: #{path} matches no supported image " \
      "format (JPEG/PNG/GIF/WebP).")
  end
  allowed = Parse::Embeddings.allowed_image_types
  unless allowed.include?(mime)
    raise ImageFetch::InvalidImageType.new(:type_not_allowed,
      "Parse::Embeddings::MediaFile.image: sniffed type #{mime.inspect} is not in " \
      "Parse::Embeddings.allowed_image_types (#{allowed.inspect}).")
  end
  new(path: path, mime_type: mime, kind: :image)
end

.video(path) ⇒ MediaFile

Wrap a local video file. Verifies the magic bytes against Parse::Embeddings.allowed_video_types.

Parameters:

Returns:

Raises:



76
77
78
79
# File 'lib/parse/embeddings/media_file.rb', line 76

def video(path)
  header = read_header(path)
  new(path: path, mime_type: VideoSource.verify!(header), kind: :video)
end

Instance Method Details

#data_uri_prefixString

The data: URI prefix that precedes the streamed base64 in the wire body. The payload itself is never concatenated here.

Returns:



118
119
120
# File 'lib/parse/embeddings/media_file.rb', line 118

def data_uri_prefix
  "data:#{mime_type};base64,"
end

#inspectObject Also known as: to_s



129
130
131
132
# File 'lib/parse/embeddings/media_file.rb', line 129

def inspect
  "#<Parse::Embeddings::MediaFile kind=#{@kind} mime_type=#{@mime_type.inspect} " \
  "bytes=#{@byte_size} path=#{@path.inspect}>"
end

#stream_segmentHash

Segment descriptor consumed by StreamingBody.

Returns:



125
126
127
# File 'lib/parse/embeddings/media_file.rb', line 125

def stream_segment
  { path: @path, size: @byte_size }
end