Skip to content

Commit 60dfd06

Browse files
Display VTT transcripts in audio/video players (#7418)
* Add transcript_ids property to file set model(s) * Add transcript_ids to file set form * Copy changes from @kirkkwang's draft PR, WIP: Implement Transcription Support in Hyrax #7380 https://github.com/samvera/hyrax/pull/7380/changes * Support transcriptions for ActiveFedora works * Fix broken specs * Normalize VTT file set language values to 2-letter language codes. * Simplify iiif_manifest_presenter_spec#annotates_content * Add comments and rubocop fixes * Add language field to file set form and move transcript ids form hint into simple form * Add VTT transcripts to default audio/video partials * Fix "l is not a function" error when displaying VTT transcripts in Annotations tab of Clover IIIF viewer. "l" is supposed to refer to the <ItemStyled> object in Annotation (https://github.com/samvera-labs/clover-iiif/blob/main/src/components/Viewer/InformationPanel/Annotation/Item.styled.tsx). In the minified version of this file, this should actually be uppercase L, not lowercase l. `l("span",{style:{backgroundImage` was changed to `L("span",{style:{backgroundImage` `return l(n9,{dir:P,"data-format"` was changed to `return L(n9,{dir:P,"data-format"` There appears to be an unnecessary call to `l()` in the following switch/case statement: ``` case "text/vtt": return l(HQ, { inlineCues: k, label: A, vttUri: ((D = y[0]) == null ? void 0 : D.id) || void 0 }); ``` In fact, `return l(HQ,{inlineCues:k` can be changed to `return HQ({inlineCues:k` since HQ is a function in the minified file. * Fix "l is not a function" error for other file types. The implementation for other file types seems unfinished and doesn't work. * Use the file set presenter to render the file set edit form instead of the solr document. Do not make language a required field for a file set. * Allow transcriptions_controller to serve file types other than VTT. Fix some formatting and specs. * Fix syntax error in clover.js * Increase the height of Clover IIIF viewer so that thumbnails for works with multiple files are visible. * Rename "transcriptions" to "transcripts" for consistency * Account for ActiveTriples::Resource in a transcript's language field. Remove tests for code that was already tested/covered elsewhere. * Remove unused fallback label, since a file set should always have a title or label * Make language optional again in IIIF manifest annotations, especially since it's not required by the viewer. * Delete a stray, unnecessary comment * Rename .valid_transcripts to .available_transcripts * Update file_set_form_helper_spec.rb * Fixes for Koppie: use file_ids_ssim.first instead of original_file_id * Fix and refactor file_set_form_helper_spec to use top-level context blocks (instead of describe) * Rubocop fixes and add comment * Refactor file set form * Use cached parent for FileSetFormHelper instead of running an extra query. Rename form_transcript_ids_select_for to transcript_ids_select_options * Add vtt file metadata to file_set_form_helper_spec * When searching for available transcripts. use an fq filter to capture both FileSets and Hyrax::FileSets. * Fix whitespace and add some clarifying comments. * Authorize transcript before streaming the file * Remove test for ActiveTriples::Resource in presenters/hyrax/displays_transcripts. It was created for a hypothetical edge case in which someone might configure a controlled vocabulary field (e.g. Hyrax::ControlledVocabularies::Language) in an AF-based app. Removed since it doesn't refer to any existing use case in Hyrax. * Make `transcript_ids` property conditional on Hyrax.config.file_set_include_metadata. Add `transcript_ids` to default flexible metadata profiles. * Update metadata profiles to fix allinson and koppie builds * Move the transcripts_ids form field to views/records/edit_fields so it can be optional for apps with flexible metadata. * Move transcript_ids into the file set metadata schema * Update clover.js to v.3.6.0, which officially fixes samvera-labs/clover-iiif#305 --------- Co-authored-by: Rob Kaufman <rob@notch8.com>
1 parent 8a6d964 commit 60dfd06

51 files changed

Lines changed: 1166 additions & 193 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.dassie/config/metadata_profiles/m3_profile.yaml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -942,3 +942,17 @@ properties:
942942
view:
943943
render_as: faceted
944944
html_dl: true
945+
transcript_ids:
946+
available_on:
947+
class:
948+
- Hyrax::FileSet
949+
indexing:
950+
- transcript_ids_ssim
951+
data_type: array
952+
display_label:
953+
default: Transcripts
954+
form:
955+
display: true
956+
primary: false
957+
range: http://www.w3.org/2001/XMLSchema#string
958+
property_uri: http://vocabulary.samvera.org/ns#transcriptIds

.koppie/config/metadata_profiles/m3_profile.yaml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -914,3 +914,17 @@ properties:
914914
view:
915915
render_as: faceted
916916
html_dl: true
917+
transcript_ids:
918+
available_on:
919+
class:
920+
- FileSet
921+
indexing:
922+
- transcript_ids_ssim
923+
data_type: array
924+
display_label:
925+
default: Transcripts
926+
form:
927+
display: true
928+
primary: false
929+
range: http://www.w3.org/2001/XMLSchema#string
930+
property_uri: http://vocabulary.samvera.org/ns#transcriptIds

app/assets/stylesheets/hyrax/_viewer.scss

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,17 @@
1111
left: 0;
1212
}
1313

14+
// Universal Viewer:
1415
// Show various footer, header, left and right panels on larger screens only
1516
@media only screen and (min-width: 640px) {
1617
.viewer-wrapper {
1718
height: 640px;
1819
}
20+
}
21+
22+
// Clover IIIF Viewer:
23+
// Increase the height so that thumbnails below the player are visible
24+
// (for works with multiple audio/video files)
25+
.viewer-wrapper.clover-viewer-wrapper {
26+
height: 775px;
1927
}

app/controllers/concerns/hyrax/works_controller_behavior.rb

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -139,12 +139,15 @@ def inspect_work
139139
end
140140

141141
def manifest
142-
headers['Access-Control-Allow-Origin'] = '*'
142+
locale = params[:locale] || current_user&.preferred_locale || I18n.default_locale
143+
I18n.with_locale(locale) do
144+
headers['Access-Control-Allow-Origin'] = '*'
143145

144-
json = iiif_manifest_builder.manifest_for(presenter: iiif_manifest_presenter)
146+
json = iiif_manifest_builder.manifest_for(presenter: iiif_manifest_presenter)
145147

146-
respond_to do |wants|
147-
wants.any { render json: json }
148+
respond_to do |wants|
149+
wants.any { render json: json }
150+
end
148151
end
149152
end
150153

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# frozen_string_literal: true
2+
3+
module Hyrax
4+
class TranscriptsController < DownloadsController
5+
def show
6+
# Using the extracted text from the index is blocked
7+
# by https://github.com/samvera/hyrax/issues/7410, so we
8+
# need to get the original file instead.
9+
file_metadata = find_file_metadata(file_set: Hyrax.query_service.find_by(id: params.require(:id)))
10+
file = Hyrax.storage_adapter.find_by(id: file_metadata.file_identifier)
11+
12+
prepare_file_headers_valkyrie(metadata: file_metadata, file: file)
13+
response.headers['Access-Control-Allow-Origin'] = '*'
14+
send_file file.disk_path, data_options(file_metadata)
15+
end
16+
17+
private
18+
19+
def disposition
20+
'inline'
21+
end
22+
23+
def data_options(file_metadata)
24+
{
25+
type: "#{file_metadata.mime_type}; charset=utf-8",
26+
filename: file_metadata.original_filename,
27+
disposition: disposition
28+
}
29+
end
30+
end
31+
end
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# frozen_string_literal: true
2+
module Hyrax
3+
module TranscriptsBehavior
4+
extend ActiveSupport::Concern
5+
6+
class_methods do
7+
def available_transcripts(parent:, current_ability:)
8+
member_ids = Hyrax.custom_queries.find_child_file_set_ids(resource: parent)
9+
Hyrax::SolrQueryService.new
10+
# Cast Valkyrie::IDs to strings
11+
.with_ids(ids: member_ids.map(&:to_s).to_a)
12+
.accessible_by(ability: current_ability, action: :edit)
13+
.solr_documents(
14+
# Using "has_model_ssim:*FileSet" in fq will return both FileSet
15+
# and Hyrax::FileSet documents. In test mode, Koppie and Sirenia
16+
# index file sets with has_model_ssim:Hyrax::FileSet.
17+
# But in dev mode, they index file sets with
18+
# has_model_ssim:FileSet instead. This query covers both cases.
19+
fq: [mime_type_filter_query.to_s, "has_model_ssim:*FileSet"],
20+
fl: "id,title_tesim",
21+
rows: 1000
22+
)
23+
end
24+
25+
private
26+
27+
def mime_type_filter_query
28+
valid_mime_types.map { |type| "mime_type_ssi:\"#{type}\"" }.join(" OR ")
29+
end
30+
31+
# According to IIIF, .srt and .ttml are also acceptable but may
32+
# not be supported by viewers. Clover and Ramp are confirmed to work
33+
# with .vtt. (https://iiif.io/api/cookbook/recipe/0219-using-caption-file/).
34+
# When Hyrax supports Ramp, we may want to add "text/plain" (.srt) to this list.
35+
def valid_mime_types
36+
["text/vtt"]
37+
end
38+
end
39+
end
40+
end

app/forms/hyrax/forms/file_set_edit_form.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ class FileSetEditForm
1212

1313
self.terms = [:resource_type, :title, :creator, :contributor, :description,
1414
:keyword, :license, :publisher, :date_created, :subject, :language,
15-
:identifier, :based_near, :related_url,
15+
:identifier, :based_near, :related_url, :transcript_ids,
1616
:visibility_during_embargo, :visibility_after_embargo, :embargo_release_date,
1717
:visibility_during_lease, :visibility_after_lease, :lease_expiration_date,
1818
:visibility]

app/forms/hyrax/forms/file_set_form.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ class FileSetForm < Hyrax::Forms::ResourceForm
1414
include Hyrax::ContainedInWorksBehavior
1515
include Hyrax::LeaseabilityBehavior
1616
include Hyrax::PermissionBehavior
17+
include Hyrax::TranscriptsBehavior
1718

1819
property :representative_id, type: Valkyrie::Types::String, writeable: false
1920
property :thumbnail_id, type: Valkyrie::Types::String, writeable: false
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# frozen_string_literal: true
2+
3+
module Hyrax
4+
module FileSetFormHelper
5+
def render_transcript_ids_field?(file_set)
6+
return unless file_set.persisted?
7+
return if @parent.nil?
8+
case file_set
9+
when ActiveFedora::Base
10+
file_set.video? || file_set.audio?
11+
when Valkyrie::Resource
12+
service = Hyrax::FileSetTypeService.new(file_set: file_set)
13+
service.video? || service.audio?
14+
end
15+
end
16+
17+
def transcript_ids_select_options
18+
options = Forms::FileSetForm.available_transcripts(parent: @parent, current_ability: current_ability)
19+
options.each_with_object({}) do |doc, hash|
20+
hash[doc.title_or_label] = doc.id.to_s
21+
end
22+
end
23+
end
24+
end

app/helpers/hyrax/hyrax_helper_behavior.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ module HyraxHelperBehavior
2121
include Hyrax::FacetsHelper
2222
include Hyrax::AttributesHelper
2323
include Hyrax::WorksHelper
24+
include Hyrax::FileSetFormHelper
2425

2526
##
2627
# @return [Array<String>] the list of admin sets available for creating works for this user

0 commit comments

Comments
 (0)