Skip to content

Commit 6c63af3

Browse files
authored
Merge pull request DSpace#1967 from yingjin/DA-8586
Add captioning support for video/audio files
2 parents 2fbfdd0 + 9627ebb commit 6c63af3

6 files changed

Lines changed: 250 additions & 4 deletions

File tree

src/app/core/shared/media-viewer-item.model.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@ export class MediaViewerItem {
1414
*/
1515
format: string;
1616

17+
/**
18+
* Incoming Bitsream format mime type
19+
*/
20+
mimetype: string;
21+
1722
/**
1823
* Incoming Bitsream thumbnail
1924
*/
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/*
2+
The class is designed to host information related to Video Captioning support
3+
and used in HTML 5 video track
4+
src: source vtt file
5+
srclang: two letter language code
6+
langLabel: language label
7+
*/
8+
export class CaptionInfo {
9+
constructor(public src: string, public srclang: string, public langLabel: string ) {
10+
}
11+
}
Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
export const languageHelper = {
2+
ab: 'Abkhazian',
3+
aa: 'Afar',
4+
af: 'Afrikaans',
5+
ak: 'Akan',
6+
sq: 'Albanian',
7+
am: 'Amharic',
8+
ar: 'Arabic',
9+
an: 'Aragonese',
10+
hy: 'Armenian',
11+
as: 'Assamese',
12+
av: 'Avaric',
13+
ae: 'Avestan',
14+
ay: 'Aymara',
15+
az: 'Azerbaijani',
16+
bm: 'Bambara',
17+
ba: 'Bashkir',
18+
eu: 'Basque',
19+
be: 'Belarusian',
20+
bn: 'Bengali (Bangla)',
21+
bh: 'Bihari',
22+
bi: 'Bislama',
23+
bs: 'Bosnian',
24+
br: 'Breton',
25+
bg: 'Bulgarian',
26+
my: 'Burmese',
27+
ca: 'Catalan',
28+
ch: 'Chamorro',
29+
ce: 'Chechen',
30+
ny: 'Chichewa, Chewa, Nyanja',
31+
zh: 'Chinese',
32+
cv: 'Chuvash',
33+
kw: 'Cornish',
34+
co: 'Corsican',
35+
cr: 'Cree',
36+
hr: 'Croatian',
37+
cs: 'Czech',
38+
da: 'Danish',
39+
dv: 'Divehi, Dhivehi, Maldivian',
40+
nl: 'Dutch',
41+
dz: 'Dzongkha',
42+
en: 'English',
43+
eo: 'Esperanto',
44+
et: 'Estonian',
45+
ee: 'Ewe',
46+
fo: 'Faroese',
47+
fj: 'Fijian',
48+
fi: 'Finnish',
49+
fr: 'French',
50+
ff: 'Fula, Fulah, Pulaar, Pular',
51+
gl: 'Galician',
52+
gd: 'Gaelic (Scottish)',
53+
gv: 'Gaelic (Manx)',
54+
ka: 'Georgian',
55+
de: 'German',
56+
el: 'Greek',
57+
gn: 'Guarani',
58+
gu: 'Gujarati',
59+
ht: 'Haitian Creole',
60+
ha: 'Hausa',
61+
he: 'Hebrew',
62+
hz: 'Herero',
63+
hi: 'Hindi',
64+
ho: 'Hiri Motu',
65+
hu: 'Hungarian',
66+
is: 'Icelandic',
67+
io: 'Ido',
68+
ig: 'Igbo',
69+
in: 'Indonesian',
70+
ia: 'Interlingua',
71+
ie: 'Interlingue',
72+
iu: 'Inuktitut',
73+
ik: 'Inupiak',
74+
ga: 'Irish',
75+
it: 'Italian',
76+
ja: 'Japanese',
77+
jv: 'Javanese',
78+
kl: 'Kalaallisut, Greenlandic',
79+
kn: 'Kannada',
80+
kr: 'Kanuri',
81+
ks: 'Kashmiri',
82+
kk: 'Kazakh',
83+
km: 'Khmer',
84+
ki: 'Kikuyu',
85+
rw: 'Kinyarwanda (Rwanda)',
86+
rn: 'Kirundi',
87+
ky: 'Kyrgyz',
88+
kv: 'Komi',
89+
kg: 'Kongo',
90+
ko: 'Korean',
91+
ku: 'Kurdish',
92+
kj: 'Kwanyama',
93+
lo: 'Lao',
94+
la: 'Latin',
95+
lv: 'Latvian (Lettish)',
96+
li: 'Limburgish ( Limburger)',
97+
ln: 'Lingala',
98+
lt: 'Lithuanian',
99+
lu: 'Luga-Katanga',
100+
lg: 'Luganda, Ganda',
101+
lb: 'Luxembourgish',
102+
mk: 'Macedonian',
103+
mg: 'Malagasy',
104+
ms: 'Malay',
105+
ml: 'Malayalam',
106+
mt: 'Maltese',
107+
mi: 'Maori',
108+
mr: 'Marathi',
109+
mh: 'Marshallese',
110+
mo: 'Moldavian',
111+
mn: 'Mongolian',
112+
na: 'Nauru',
113+
nv: 'Navajo',
114+
ng: 'Ndonga',
115+
nd: 'Northern Ndebele',
116+
ne: 'Nepali',
117+
no: 'Norwegian',
118+
nb: 'Norwegian bokmål',
119+
nn: 'Norwegian nynorsk',
120+
oc: 'Occitan',
121+
oj: 'Ojibwe',
122+
cu: 'Old Church Slavonic, Old Bulgarian',
123+
or: 'Oriya',
124+
om: 'Oromo (Afaan Oromo)',
125+
os: 'Ossetian',
126+
pi: 'Pāli',
127+
ps: 'Pashto, Pushto',
128+
fa: 'Persian (Farsi)',
129+
pl: 'Polish',
130+
pt: 'Portuguese',
131+
pa: 'Punjabi (Eastern)',
132+
qu: 'Quechua',
133+
rm: 'Romansh',
134+
ro: 'Romanian',
135+
ru: 'Russian',
136+
se: 'Sami',
137+
sm: 'Samoan',
138+
sg: 'Sango',
139+
sa: 'Sanskrit',
140+
sr: 'Serbian',
141+
sh: 'Serbo-Croatian',
142+
st: 'Sesotho',
143+
tn: 'Setswana',
144+
sn: 'Shona',
145+
ii: 'Sichuan Yi, Nuosu',
146+
sd: 'Sindhi',
147+
si: 'Sinhalese',
148+
ss: 'Siswati (Swati)',
149+
sk: 'Slovak',
150+
sl: 'Slovenian',
151+
so: 'Somali',
152+
nr: 'Southern Ndebele',
153+
es: 'Spanish',
154+
su: 'Sundanese',
155+
sw: 'Swahili (Kiswahili)',
156+
sv: 'Swedish',
157+
tl: 'Tagalog',
158+
ty: 'Tahitian',
159+
tg: 'Tajik',
160+
ta: 'Tamil',
161+
tt: 'Tatar',
162+
te: 'Telugu',
163+
th: 'Thai',
164+
bo: 'Tibetan',
165+
ti: 'Tigrinya',
166+
to: 'Tonga',
167+
ts: 'Tsonga',
168+
tr: 'Turkish',
169+
tk: 'Turkmen',
170+
tw: 'Twi',
171+
ug: 'Uyghur',
172+
uk: 'Ukrainian',
173+
ur: 'Urdu',
174+
uz: 'Uzbek',
175+
ve: 'Venda',
176+
vi: 'Vietnamese',
177+
vo: 'Volapük',
178+
wa: 'Wallon',
179+
cy: 'Welsh',
180+
wo: 'Wolof',
181+
fy: 'Western Frisian',
182+
xh: 'Xhosa',
183+
yi: 'Yiddish',
184+
yo: 'Yoruba',
185+
za: 'Zhuang, Chuang',
186+
zu: 'Zulu'
187+
};
188+
189+
190+

src/app/item-page/media-viewer/media-viewer-video/media-viewer-video.component.html

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
<video
2+
crossorigin="anonymous"
23
#media
34
[src]="filteredMedias[currentIndex].bitstream._links.content.href"
45
id="singleVideo"
@@ -8,7 +9,14 @@
89
"
910
preload="none"
1011
controls
11-
></video>
12+
>
13+
<ng-container *ngIf="getMediaCap(filteredMedias[currentIndex].bitstream.name) as capInfos">
14+
<ng-container *ngFor="let capInfo of capInfos">
15+
<track [src]="capInfo.src" [label]="capInfo.langLabel" [srclang]="capInfo.srclang" />
16+
</ng-container>
17+
</ng-container>
18+
19+
</video>
1220
<div class="buttons" *ngIf="filteredMedias?.length > 1">
1321
<button
1422
class="btn btn-primary previous"

src/app/item-page/media-viewer/media-viewer-video/media-viewer-video.component.ts

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import { Component, Input, OnInit } from '@angular/core';
22
import { MediaViewerItem } from '../../../core/shared/media-viewer-item.model';
3+
import { languageHelper } from './language-helper';
4+
import { CaptionInfo} from './caption-info';
35

46
/**
57
* This componenet renders a video viewer and playlist for the media viewer
@@ -26,9 +28,38 @@ export class MediaViewerVideoComponent implements OnInit {
2628

2729
ngOnInit() {
2830
this.isCollapsed = false;
29-
this.filteredMedias = this.medias.filter(
30-
(media) => media.format === 'audio' || media.format === 'video'
31-
);
31+
this.filteredMedias = this.medias.filter((media) => media.format === 'audio' || media.format === 'video');
32+
}
33+
34+
/**
35+
* This method check if there is caption file for the media
36+
* The caption file name is the media name plus "-" following two letter
37+
* language code and .vtt suffix
38+
*
39+
* html5 video only support WEBVTT format
40+
*
41+
* Two letter language code reference
42+
* https://www.w3schools.com/tags/ref_language_codes.asp
43+
*/
44+
getMediaCap(name: string): CaptionInfo[] {
45+
let filteredCapMedias: MediaViewerItem[];
46+
let capInfos: CaptionInfo[] = [];
47+
filteredCapMedias = this.medias
48+
.filter((media) => media.mimetype === 'text/vtt')
49+
.filter((media) => media.bitstream.name.substring(0, (media.bitstream.name.length - 7) ).toLowerCase() === name.toLowerCase());
50+
51+
if (filteredCapMedias) {
52+
filteredCapMedias
53+
.forEach((media, index) => {
54+
let srclang: string = media.bitstream.name.slice(-6, -4).toLowerCase();
55+
capInfos.push(new CaptionInfo(
56+
media.bitstream._links.content.href,
57+
srclang,
58+
languageHelper[srclang]
59+
));
60+
});
61+
}
62+
return capInfos;
3263
}
3364

3465
/**

src/app/item-page/media-viewer/media-viewer.component.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ export class MediaViewerComponent implements OnInit {
108108
const mediaItem = new MediaViewerItem();
109109
mediaItem.bitstream = original;
110110
mediaItem.format = format.mimetype.split('/')[0];
111+
mediaItem.mimetype = format.mimetype;
111112
mediaItem.thumbnail = thumbnail ? thumbnail._links.content.href : null;
112113
return mediaItem;
113114
}

0 commit comments

Comments
 (0)