75 lines
2.1 KiB
Ruby
75 lines
2.1 KiB
Ruby
class MediaFile < ApplicationRecord
|
|
# Base class for all media files (Video, Audio, etc.)
|
|
# Uses Single Table Inheritance (STI) via the 'type' column
|
|
self.table_name = 'videos'
|
|
self.abstract_class = true
|
|
|
|
include Streamable
|
|
include Processable
|
|
|
|
# Common JSON stores for flexible metadata
|
|
store :fingerprints, accessors: [:xxhash64, :md5, :oshash, :phash]
|
|
store :media_metadata, accessors: [:duration, :codec, :bit_rate, :format]
|
|
|
|
# Common associations
|
|
belongs_to :work
|
|
belongs_to :storage_location
|
|
has_many :playback_sessions, dependent: :destroy
|
|
|
|
# Common validations
|
|
validates :filename, presence: true
|
|
validates :xxhash64, presence: true, uniqueness: { scope: :storage_location_id }
|
|
|
|
# Common scopes
|
|
scope :web_compatible, -> { where(web_compatible: true) }
|
|
scope :needs_transcoding, -> { where(web_compatible: false) }
|
|
scope :recent, -> { order(created_at: :desc) }
|
|
|
|
# Common delegations
|
|
delegate :display_title, to: :work, prefix: true, allow_nil: true
|
|
|
|
# Common instance methods
|
|
def display_title
|
|
work&.display_title || filename
|
|
end
|
|
|
|
def full_file_path
|
|
File.join(storage_location.path, filename)
|
|
end
|
|
|
|
def format_duration
|
|
return "Unknown" unless duration
|
|
|
|
hours = (duration / 3600).to_i
|
|
minutes = ((duration % 3600) / 60).to_i
|
|
seconds = (duration % 60).to_i
|
|
|
|
if hours > 0
|
|
"%d:%02d:%02d" % [hours, minutes, seconds]
|
|
else
|
|
"%d:%02d" % [minutes, seconds]
|
|
end
|
|
end
|
|
|
|
# Template method for subclasses to override
|
|
def web_stream_path
|
|
# Default implementation - subclasses can override for specific behavior
|
|
if transcoded_permanently? && transcoded_path && File.exist?(transcoded_full_path)
|
|
return transcoded_full_path
|
|
end
|
|
if transcoded_path && File.exist?(temp_transcoded_full_path)
|
|
return temp_transcoded_full_path
|
|
end
|
|
full_file_path if web_compatible?
|
|
end
|
|
|
|
def transcoded_full_path
|
|
return nil unless transcoded_path
|
|
File.join(storage_location.path, transcoded_path)
|
|
end
|
|
|
|
def temp_transcoded_full_path
|
|
return nil unless transcoded_path
|
|
File.join(Rails.root, 'tmp', 'transcodes', storage_location.id.to_s, transcoded_path)
|
|
end
|
|
end |