Class: SeleniumScreencast::FrameStore

Inherits:
Object
  • Object
show all
Defined in:
lib/selenium_screencast/frame_store.rb

Overview

Saves received JPEG frames to disk with sequential numbering, and holds the frame metadata. Deals only with the filesystem and has no dependency on selenium, so it can be tested standalone.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(dir) ⇒ FrameStore

Returns a new instance of FrameStore.



27
28
29
30
31
32
# File 'lib/selenium_screencast/frame_store.rb', line 27

def initialize(dir)
  @dir = Pathname(dir.to_s)
  FileUtils.mkdir_p(@dir)
  @frames = []
  @mutex = Mutex.new
end

Instance Attribute Details

#framesObject (readonly)

Frame info in the order received. Each element is { file:, time:, size: }. The key names match the original implementation (passed on to Encoder). size: is the byte size of the written JPEG, recorded so Encoder can use it as a fast-path rejection when comparing frames for staticness, without having to read the frame back from disk.



16
17
18
# File 'lib/selenium_screencast/frame_store.rb', line 16

def frames
  @frames
end

Class Method Details

.for_output(output_path) ⇒ Object

Builds a FrameStore by deriving the frame directory from the output file path. Frame images are placed in "_frames" in the same directory as the output file.



21
22
23
24
25
# File 'lib/selenium_screencast/frame_store.rb', line 21

def self.for_output(output_path)
  path = Pathname(output_path.to_s)
  frames_dir = path.dirname.join("#{path.basename(".*")}_frames")
  new(frames_dir)
end

Instance Method Details

#cleanup(keep:) ⇒ Object

Removes the entire frame directory unless keep is true.



58
59
60
# File 'lib/selenium_screencast/frame_store.rb', line 58

def cleanup(keep:)
  FileUtils.rm_rf(@dir) unless keep
end

#write(jpeg_bytes, timestamp:) ⇒ Object

Writes the JPEG byte string sequentially as 0001.jpg, and so on, and appends the metadata to frames. The index matches the original implementation: @frames.size + 1 (starting at 0001). CDP runs the callback on a new thread for every screencastFrame event, so numbering, writing, and appending are all serialized under a Mutex to prevent frame collisions or loss.



40
41
42
43
44
45
46
47
# File 'lib/selenium_screencast/frame_store.rb', line 40

def write(jpeg_bytes, timestamp:)
  @mutex.synchronize do
    index = @frames.size + 1
    file = @dir.join(format("%04d.jpg", index))
    File.binwrite(file, jpeg_bytes)
    @frames << { file: file.to_s, time: timestamp, size: jpeg_bytes.bytesize }
  end
end

#write_concat_list(content) ⇒ Object

Writes the concat demuxer list to concat.txt in the frame directory, and returns its path.



51
52
53
54
55
# File 'lib/selenium_screencast/frame_store.rb', line 51

def write_concat_list(content)
  path = concat_path
  File.write(path, content)
  path
end