Skip to content

Commit

Permalink
handle multiple caption files (#1765)
Browse files Browse the repository at this point in the history
  • Loading branch information
hudajkhan authored Nov 20, 2023
1 parent b871bd7 commit 287f40f
Show file tree
Hide file tree
Showing 7 changed files with 69 additions and 35 deletions.
34 changes: 32 additions & 2 deletions app/components/embed/media_tag_component.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,16 @@ class MediaTagComponent < ViewComponent::Base # rubocop:disable Metrics:ClassLen
include StacksImage
with_collection_parameter :resource
SUPPORTED_MEDIA_TYPES = %i[audio video].freeze
# Hardcoding some language code to label mappings, based on the mappings we currently need.
# This approach should be revisited once we have more robust BCP 47 code to label mapping integrated.
FILE_LANGUAGE_CAPTION_LABELS = {
'en' => 'English',
'ru' => 'Russian',
'de' => 'German',
'et' => 'Estonian',
'lv' => 'Latvian',
'es' => 'Spanish'
}.freeze

# @param [Purl::Resource] resource This resource is expected to have a primary file.
# @param [#index] resource_iteration Information about what part of the collection we are in
Expand Down Expand Up @@ -102,14 +112,34 @@ def enabled_streaming_sources
)
end

# Generate the video caption elements
def transcript
return unless render_captions?

tag.track(src: @resource.vtt.file_url, kind: 'captions', srclang: 'en', label: 'English')
# A video clip may have multiple caption files in different languages.
# We want to enable the user to select from any of these options.
# We also want the different language options to be listed alphabetically.
safe_join(
sort_caption_tracks(@resource.caption_files).map do |caption_file|
lang_code = caption_file.language || 'en'
lang_label = caption_language(lang_code)
tag.track(src: caption_file.file_url, kind: 'captions', srclang: lang_code, label: lang_label)
end
)
end

# Sort the caption files by language label so we can display them in alphabetical order in the
# captions options list.
def sort_caption_tracks(caption_files)
caption_files.sort_by { |cfile| caption_language(cfile.language) }
end

def caption_language(language_code)
FILE_LANGUAGE_CAPTION_LABELS.fetch(language_code, 'Caption')
end

def render_captions?
@include_transcripts && @resource.vtt
@include_transcripts && @resource.caption_files
end

# NOTE: This is only for the legacy media player. We can remove it when we switch to the new player.
Expand Down
3 changes: 3 additions & 0 deletions app/models/embed/purl/file_xml_deserializer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,14 @@ def duration
Embed::MediaDuration.new(@file.xpath('./*[@duration]').first).to_s
end

# rubocop:disable Metrics/AbcSize
def deserialize
ResourceFile.new(
druid: @druid,
label: @description,
mimetype: @file.attributes['mimetype']&.value,
size: @file.attributes['size']&.value.to_i,
language: @file.attributes['language']&.value,
filename:,
stanford_only:,
location_restricted:,
Expand All @@ -50,6 +52,7 @@ def deserialize
file.duration = duration
end
end
# rubocop:enable Metrics/AbcSize
end
end
end
6 changes: 3 additions & 3 deletions app/models/embed/purl/resource.rb
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@ def thumbnail
files.find(&:image?)
end

# @return [ResourceFile]
def vtt
files.find(&:vtt?)
# @return [Array<ResourceFile>]
def caption_files
files.select(&:vtt?)
end
end
end
Expand Down
2 changes: 1 addition & 1 deletion app/models/embed/purl/resource_file.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def attributes=(hash)
end
end

attr_accessor :druid, :label, :filename, :mimetype, :size, :duration,
attr_accessor :druid, :label, :filename, :mimetype, :size, :duration, :language,
:world_downloadable, :stanford_only, :location_restricted

alias title filename
Expand Down
27 changes: 27 additions & 0 deletions spec/components/embed/media_tag_component_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -223,4 +223,31 @@
expect(page).to have_css('track[src="https://stacks.stanford.edu/file/druid:bc123df4567/abc_123_cap.webvtt"]')
end
end

context 'with captions for multiple languages' do
let(:resource) do
build(:resource, :video, files: [build(:resource_file, :video),
build(:resource_file, :vtt, language: 'en'),
build(:resource_file, :vtt, language: 'ru')])
end

let(:include_transcripts) { true }

it 'has track elements with multiple languages' do
expect(page).to have_css('track[srclang="en"][label="English"]')
expect(page).to have_css('track[srclang="ru"][label="Russian"]')
end
end

context 'with caption with no specified language' do
let(:resource) do
build(:resource, :video, files: [build(:resource_file, :video),
build(:resource_file, :vtt)])
end
let(:include_transcripts) { true }

it 'has a track element with code and label for English' do
expect(page).to have_css('track[srclang="en"][label="English"]')
end
end
end
26 changes: 0 additions & 26 deletions spec/fixtures/purl_fixtures.rb
Original file line number Diff line number Diff line change
Expand Up @@ -848,32 +848,6 @@ def single_video_purl
XML
end

def video_purl_with_vtt
<<-XML
<publicObject>
<identityMetadata>
<objectLabel>Title of the single video</objectLabel>
</identityMetadata>
<contentMetadata type="media">
<resource sequence="1" id="abc123_1" type="video">
<file id="abc_123.mp4" mimetype="video/mp4" size="152000000"></file>
<file id="abc_123_cap.webvtt" mimetype="text/vtt" size="176218"></file>
</resource>
</contentMetadata>
<rightsMetadata>
<access type="read">
<machine>
<location>spec</location>
</machine>
</access>
</rightsMetadata>
<oai_dc:dc xmlns:oai_dc="http://www.openarchives.org/OAI/2.0/oai_dc/" xmlns:dc="http://purl.org/dc/elements/1.1/">
<dc:title>title of video with vtt</dc:title>
</oai_dc>
</publicObject>
XML
end

def video_purl
<<-XML
<publicObject>
Expand Down
6 changes: 3 additions & 3 deletions spec/models/embed/purl/resource_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -60,17 +60,17 @@
end
end

describe '#vtt' do
describe '#caption_files' do
context 'when it has a vtt transcript' do
subject { resource.vtt.title }
subject { resource.caption_files[0].title }

let(:resource) { build(:resource, :video) }

it { is_expected.to eq 'abc_123_cap.webvtt' }
end

context 'when it does not have a vtt transcript' do
subject { resource.vtt }
subject { resource.caption_files[0] }

let(:resource) { build(:resource, :video, files: [build(:resource_file, :video)]) }

Expand Down

0 comments on commit 287f40f

Please sign in to comment.