Skip to content

Commit

Permalink
Merge pull request #6042 from avalonmediasystem/prog_downloads
Browse files Browse the repository at this point in the history
Allow manual loading of records with progressive download streams instead of HLS streams
  • Loading branch information
cjcolvar authored Sep 24, 2024
2 parents 4b24aca + 1ca8d2f commit 66f9c0c
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 23 deletions.
30 changes: 19 additions & 11 deletions app/models/iiif_canvas_presenter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -98,21 +98,29 @@ def service

def video_content
# @see https://github.com/samvera-labs/iiif_manifest
stream_urls.collect { |quality, _url| video_display_content(quality) }
stream_urls.collect { |quality, url, mimetype| video_display_content(quality, url, mimetype) }
end

def video_display_content(quality)
IIIFManifest::V3::DisplayContent.new(Rails.application.routes.url_helpers.hls_manifest_master_file_url(master_file.id, quality: quality),
**manifest_attributes(quality, 'Video'))
def video_display_content(quality, url, mimetype)
if mimetype.present? && mimetype != 'application/x-mpegURL'
IIIFManifest::V3::DisplayContent.new(url, **manifest_attributes(quality, 'Video', mimetype: mimetype))
else
IIIFManifest::V3::DisplayContent.new(Rails.application.routes.url_helpers.hls_manifest_master_file_url(master_file.id, quality: quality),
**manifest_attributes(quality, 'Video'))
end
end

def audio_content
stream_urls.collect { |quality, _url| audio_display_content(quality) }
stream_urls.collect { |quality, url, mimetype| audio_display_content(quality, url, mimetype) }
end

def audio_display_content(quality)
IIIFManifest::V3::DisplayContent.new(Rails.application.routes.url_helpers.hls_manifest_master_file_url(master_file.id, quality: quality),
**manifest_attributes(quality, 'Sound'))
def audio_display_content(quality, url, mimetype)
if mimetype.present? && mimetype != 'application/x-mpegURL'
IIIFManifest::V3::DisplayContent.new(url, **manifest_attributes(quality, 'Sound', mimetype: mimetype))
else
IIIFManifest::V3::DisplayContent.new(Rails.application.routes.url_helpers.hls_manifest_master_file_url(master_file.id, quality: quality),
**manifest_attributes(quality, 'Sound'))
end
end

def supplementing_content_data(file)
Expand Down Expand Up @@ -142,7 +150,7 @@ def supplementing_content_data(file)

def stream_urls
stream_info[:stream_hls].collect do |d|
[d[:quality], d[:url]]
[d[:quality], d[:url], d[:mimetype]]
end
end

Expand Down Expand Up @@ -214,14 +222,14 @@ def parse_hour_min_sec(s)
smh[0] + (60 * smh[1]) + (3600 * smh[2])
end

def manifest_attributes(quality, media_type)
def manifest_attributes(quality, media_type, mimetype: 'application/x-mpegURL')
media_hash = {
label: quality,
width: (master_file.width || '1280').to_i,
height: (master_file.height || MasterFile::AUDIO_HEIGHT).to_i,
duration: stream_info[:duration],
type: media_type,
format: 'application/x-mpegURL'
format: mimetype
}.compact

if master_file.media_object.visibility == 'public'
Expand Down
30 changes: 19 additions & 11 deletions app/models/iiif_playlist_canvas_presenter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -115,21 +115,29 @@ def metadata_field(label, value, default = nil)

def video_content
# @see https://github.com/samvera-labs/iiif_manifest
stream_urls.collect { |quality, _url| video_display_content(quality) }
stream_urls.collect { |quality, url, mimetype| video_display_content(quality, url, mimetype) }
end

def video_display_content(quality)
IIIFManifest::V3::DisplayContent.new(CGI.unescape(Rails.application.routes.url_helpers.hls_manifest_master_file_url(master_file.id, quality: quality, anchor: fragment_identifier)),
**manifest_attributes(quality, 'Video'))
def video_display_content(quality, url, mimetype)
if mimetype.present? && mimetype != 'application/x-mpegURL'
IIIFManifest::V3::DisplayContent.new(URI.join(url, "##{fragment_identifier}").to_s, **manifest_attributes(quality, 'Video', mimetype: mimetype))
else
IIIFManifest::V3::DisplayContent.new(CGI.unescape(Rails.application.routes.url_helpers.hls_manifest_master_file_url(master_file.id, quality: quality, anchor: fragment_identifier)),
**manifest_attributes(quality, 'Video'))
end
end

def audio_content
stream_urls.collect { |quality, _url| audio_display_content(quality) }
stream_urls.collect { |quality, url, mimetype| audio_display_content(quality, url, mimetype) }
end

def audio_display_content(quality)
IIIFManifest::V3::DisplayContent.new(CGI.unescape(Rails.application.routes.url_helpers.hls_manifest_master_file_url(master_file.id, quality: quality, anchor: fragment_identifier)),
**manifest_attributes(quality, 'Sound'))
def audio_display_content(quality, url, mimetype)
if mimetype.present? && mimetype != 'application/x-mpegURL'
IIIFManifest::V3::DisplayContent.new(URI.join(url, "##{fragment_identifier}").to_s, **manifest_attributes(quality, 'Sound', mimetype: mimetype))
else
IIIFManifest::V3::DisplayContent.new(CGI.unescape(Rails.application.routes.url_helpers.hls_manifest_master_file_url(master_file.id, quality: quality, anchor: fragment_identifier)),
**manifest_attributes(quality, 'Sound'))
end
end

def marker_content(marker)
Expand Down Expand Up @@ -174,7 +182,7 @@ def supplemental_attributes(file)

def stream_urls
stream_info[:stream_hls].collect do |d|
[d[:quality], d[:url]]
[d[:quality], d[:url], d[:mimetype]]
end
end

Expand All @@ -192,14 +200,14 @@ def simple_iiif_range(label = stream_info[:embed_title])
)
end

def manifest_attributes(quality, media_type)
def manifest_attributes(quality, media_type, mimetype: 'application/x-mpegURL')
media_hash = {
label: quality,
width: (master_file.width || '1280').to_i,
height: (master_file.height || MasterFile::AUDIO_HEIGHT).to_i,
duration: stream_info[:duration],
type: media_type,
format: 'application/x-mpegURL'
format: mimetype
}.compact

if master_file.media_object.visibility == 'public'
Expand Down
3 changes: 2 additions & 1 deletion spec/factories/derivatives.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@
video_bitrate { '4000000.0' }
audio_codec { 'AAC' }
audio_bitrate { '163842.0' }
absolute_location { 'file:///srv/avalon/content/6f69c008-06a4-4bad-bb60-26297f0b4c06/35bddaa0-fbb4-404f-ab76-58f22921529c/warning.mp4' }
mime_type { nil }
derivativeFile { 'file:///srv/avalon/content/6f69c008-06a4-4bad-bb60-26297f0b4c06/35bddaa0-fbb4-404f-ab76-58f22921529c/warning.mp4' }

trait :with_master_file do
after(:create) do |d|
Expand Down
26 changes: 26 additions & 0 deletions spec/models/iiif_canvas_presenter_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,19 @@
expect(subject.width).to eq 1280
expect(subject.height).to eq 40
end

context 'with mp3 file' do
let(:mp3_url) { 'https://streaming.example.com/dir/file.mp3' }
let(:derivative) { FactoryBot.build(:derivative, hls_url: mp3_url, mime_type: 'audio/mpeg' ) }

it 'has format' do
expect(subject.format).to eq 'audio/mpeg'
end

it 'has progressive download url' do
expect(subject.url).to eq mp3_url
end
end
end

context 'when video file' do
Expand All @@ -72,6 +85,19 @@
expect(subject.width).to eq 1024
expect(subject.height).to eq 768
end

context 'with mp4 file' do
let(:mp4_url) { 'https://streaming.example.com/dir/file.mp4' }
let(:derivative) { FactoryBot.build(:derivative, hls_url: mp4_url, mime_type: 'video/mp4' ) }

it 'has format' do
expect(subject.format).to eq 'video/mp4'
end

it 'has progressive download url' do
expect(subject.url).to eq mp4_url
end
end
end
end

Expand Down
26 changes: 26 additions & 0 deletions spec/models/iiif_playlist_canvas_presenter_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,19 @@
expect(subject.width).to eq 1280
expect(subject.height).to eq 40
end

context 'with mp3 file' do
let(:mp3_url) { 'https://streaming.example.com/dir/file.mp3' }
let(:derivative) { FactoryBot.build(:derivative, hls_url: mp3_url, mime_type: 'audio/mpeg' ) }

it 'has format' do
expect(subject.format).to eq 'audio/mpeg'
end

it 'has progressive download url with media fragment' do
expect(subject.url).to eq "#{mp3_url}#t=#{playlist_item.start_time / 1000},#{playlist_item.end_time / 1000}"
end
end
end

context 'when video file' do
Expand All @@ -105,6 +118,19 @@
expect(subject.width).to eq 1024
expect(subject.height).to eq 768
end

context 'with mp4 file' do
let(:mp4_url) { 'https://streaming.example.com/dir/file.mp4' }
let(:derivative) { FactoryBot.build(:derivative, hls_url: mp4_url, mime_type: 'video/mp4' ) }

it 'has format' do
expect(subject.format).to eq 'video/mp4'
end

it 'has progressive download url with media fragment' do
expect(subject.url).to eq "#{mp4_url}#t=#{playlist_item.start_time / 1000},#{playlist_item.end_time / 1000}"
end
end
end

context 'when a user does not have access to a restricted item' do
Expand Down

0 comments on commit 66f9c0c

Please sign in to comment.