diff --git a/docs/examples/elephantsdream/captions.ar.vtt b/docs/examples/elephantsdream/captions.ar.vtt new file mode 100644 index 0000000000..a68a4426f0 --- /dev/null +++ b/docs/examples/elephantsdream/captions.ar.vtt @@ -0,0 +1,330 @@ +WEBVTT + +1 +00:00:15.042 --> 00:00:18.625 +...إلى... إلى الشمال يمكن أن نرى +...يمكن أن نرى الـ + +2 +00:00:18.750 --> 00:00:20.958 +...إلى اليمين يمكن أن نرى الـ + +3 +00:00:21.000 --> 00:00:23.125 +طاحنات الرؤوس... + +4 +00:00:23.208 --> 00:00:25.208 +كل شيئ آمن +آمن كلية + +5 +00:00:26.333 --> 00:00:28.333 +إيمو ؟ + +6 +00:00:28.875 --> 00:00:30.958 +! حذاري + +7 +00:00:47.125 --> 00:00:49.167 +هل أصبت ؟ + +8 +00:00:52.125 --> 00:00:54.833 +...لا أظن ذلك +وأنت ؟ + +9 +00:00:55.625 --> 00:00:57.625 +أنا بخير + +10 +00:00:57.667 --> 00:01:01.667 +،قم يا إيمو +المكان هنا غير آمن + +11 +00:01:02.208 --> 00:01:04.083 +لنذهب + +12 +00:01:04.167 --> 00:01:06.167 +وماذا بعد ؟ + +13 +00:01:06.167 --> 00:01:08.583 +...سترى... سترى + +14 +00:01:16.167 --> 00:01:18.375 +إيمو، من هنا + +15 +00:01:34.958 --> 00:01:37.000 +! إتبعني + +16 +00:02:11.125 --> 00:02:13.625 +! أسرع يا إيمو + +17 +00:02:48.375 --> 00:02:50.375 +! لست منتبها + +18 +00:02:50.750 --> 00:02:54.500 +...أريد فقط أن أجيب الـ +الهاتف... + +19 +00:02:55.000 --> 00:02:58.500 +،إيمو، أنظر +أقصد أنصت + +20 +00:02:59.750 --> 00:03:03.292 +عليك أن تتعلم الإصغاء + +21 +00:03:03.625 --> 00:03:05.917 +هذا ليس ضربا من اللهو + +22 +00:03:06.083 --> 00:03:09.958 +...إنك +أقصد إننا قد نموت بسهولة في هذا المكان + +23 +00:03:10.208 --> 00:03:14.125 +...أنصت +أنصت إلى أصوات الآلة + +24 +00:03:18.333 --> 00:03:20.417 +أنصت إلى نَفَسِك + +25 +00:04:27.208 --> 00:04:29.250 +ألا تمل أبدا من هذا ؟ + +26 +00:04:29.583 --> 00:04:31.583 +أمل ؟!؟ +نعم - + +27 +00:04:31.750 --> 00:04:34.667 +إيمو؛ الآلة في دقتها... مثل الساعة + +28 +00:04:35.500 --> 00:04:37.708 +...حركة ناشزة واحدة قد + +29 +00:04:37.833 --> 00:04:39.875 +تطرحك معجونا + +30 +00:04:41.042 --> 00:04:43.083 +...أو ليست + +31 +00:04:43.125 --> 00:04:46.542 +! عجينة يا إيمو +أ هذا ما تريد ؟ أن تصبح عجينة ؟ + +32 +00:04:48.083 --> 00:04:50.083 +أيمو، أ هذا هدفك في الحياة ؟ + +33 +00:04:50.583 --> 00:04:52.667 +أن تصير عجينة ؟ + +34 +00:05:41.833 --> 00:05:43.875 +إيمو، أغمض عينيك + +35 +00:05:44.917 --> 00:05:47.000 +لماذا ؟ +! الآن - + +36 +00:05:53.750 --> 00:05:56.042 +حسن + +37 +00:05:59.542 --> 00:06:02.792 +ماذا ترى إلى شمالك يا إيمو ؟ + +38 +00:06:04.417 --> 00:06:06.500 +لا شيئ +حقا ؟ - + +39 +00:06:06.542 --> 00:06:08.625 +لا، لا شيئ البتة + +40 +00:06:08.625 --> 00:06:12.417 +وماذا ترى إلى جهتك اليمنى يا إيمو ؟ + +41 +00:06:13.667 --> 00:06:17.833 +،نفس الشيئ يا بروغ +! نفس الشيئ بالضبط؛ لا شيئ + +42 +00:06:17.875 --> 00:06:19.917 +عظيم + +43 +00:06:40.625 --> 00:06:42.958 +أنصت يا بروغ ! هل تسمع ذلك ؟ + +44 +00:06:43.625 --> 00:06:45.625 +هل نستطيع الذهاب إلى هناك ؟ + +45 +00:06:45.708 --> 00:06:47.792 +هناك ؟ +نعم - + +46 +00:06:47.833 --> 00:06:49.833 +إنه غير آمن يا إيمو + +47 +00:06:49.917 --> 00:06:52.500 +صدقني، إنه غير آمن + +48 +00:06:53.292 --> 00:06:55.375 +...لكن لعلي أستطيع + +49 +00:06:55.417 --> 00:06:57.417 +...لكن +! لا - + +50 +00:06:57.667 --> 00:06:59.667 +! لا + +51 +00:07:00.875 --> 00:07:03.750 +هل من أسئلة أخرى يا إيمو ؟ + +52 +00:07:04.250 --> 00:07:06.333 +لا + +53 +00:07:09.458 --> 00:07:11.542 +...إيمو +نعم - + +54 +00:07:11.875 --> 00:07:13.958 +...لماذا يا إيمو... لماذا + +55 +00:07:15.292 --> 00:07:18.792 +لماذا لا تستطيع أن ترى حُسْن هذا المكان + +56 +00:07:18.833 --> 00:07:20.833 +...والطريقة التي يعمل بها + +57 +00:07:20.875 --> 00:07:24.000 +وكيف... وكيف أنه غاية في الكمال + +58 +00:07:24.083 --> 00:07:27.417 +! لا يا بروغ، لا أرى ذلك + +59 +00:07:27.542 --> 00:07:30.333 +لا أرى ذلك لأنه لا يوجد شيئ هناك + +60 +00:07:31.500 --> 00:07:35.333 +ثم لماذا يجب علي أن أسلم حياتي +لشيئ لا وجود له ؟ + +61 +00:07:35.583 --> 00:07:37.625 +هل يمكنك أن تخبرني ؟ + +62 +00:07:37.708 --> 00:07:39.750 +! أجبني + +63 +00:07:43.208 --> 00:07:47.333 +...بروغ +! أنت معتوه يا هذا + +64 +00:07:47.375 --> 00:07:49.417 +! إبعد عني + +65 +00:07:52.583 --> 00:07:55.083 +! لا يا إيمو ! إنه فخ + +66 +00:07:55.833 --> 00:07:57.875 +...إنه فخ + +67 +00:07:57.917 --> 00:08:01.750 +إلى جنبك الأيسر يمكنك أن ترى +حدائق بابل المعلقة + +68 +00:08:02.250 --> 00:08:04.292 +هل تعجبك كفخ ؟ + +69 +00:08:05.458 --> 00:08:07.542 +لا يا أيمو + +70 +00:08:09.417 --> 00:08:12.792 +...إلى جنبك الأيمن يمكنك رؤية +حزر ماذا ؟ + +71 +00:08:13.000 --> 00:08:15.042 +! عملاق رودس + +72 +00:08:15.125 --> 00:08:16.417 +! لا + +73 +00:08:16.458 --> 00:08:20.500 +،عملاق رودس +وهو هنا خصيصا من أجلك يا بروغ + +74 +00:08:20.583 --> 00:08:22.583 +فقط من أجلك + +75 +00:08:51.333 --> 00:08:53.375 +إنه هناك + +76 +00:08:53.417 --> 00:08:55.500 +أنا أؤكد لك... إيمو + +77 +00:08:57.333 --> 00:09:00.000 +...إنه diff --git a/docs/examples/elephantsdream/captions.en.vtt b/docs/examples/elephantsdream/captions.en.vtt new file mode 100644 index 0000000000..8b83d28c11 --- /dev/null +++ b/docs/examples/elephantsdream/captions.en.vtt @@ -0,0 +1,334 @@ +WEBVTT + +1 +00:00:15.000 --> 00:00:17.951 +At the left we can see... + +2 +00:00:18.166 --> 00:00:20.083 +At the right we can see the... + +3 +00:00:20.119 --> 00:00:21.962 +...the head-snarlers + +4 +00:00:21.999 --> 00:00:24.368 +Everything is safe. +Perfectly safe. + +5 +00:00:24.582 --> 00:00:27.035 +Emo? + +6 +00:00:28.206 --> 00:00:29.996 +Watch out! + +7 +00:00:47.037 --> 00:00:48.494 +Are you hurt? + +8 +00:00:51.994 --> 00:00:53.949 +I don't think so. +You? + +9 +00:00:55.160 --> 00:00:56.985 +I'm Ok. + +10 +00:00:57.118 --> 00:01:01.111 +Get up. +Emo. it's not safe here. + +11 +00:01:02.034 --> 00:01:03.573 +Let's go. + +12 +00:01:03.610 --> 00:01:05.114 +What's next? + +13 +00:01:05.200 --> 00:01:09.146 +You'll see! + +14 +00:01:16.032 --> 00:01:18.022 +Emo. +This way. + +15 +00:01:34.237 --> 00:01:35.481 +Follow me! + +16 +00:02:11.106 --> 00:02:12.480 +Hurry Emo! + +17 +00:02:48.059 --> 00:02:49.930 +You're not paying attention! + +18 +00:02:50.142 --> 00:02:54.052 +I just want to answer the... +...phone. + +19 +00:02:54.974 --> 00:02:57.972 +Emo. look. +I mean listen. + +20 +00:02:59.140 --> 00:03:02.008 +You have to learn to listen. + +21 +00:03:03.140 --> 00:03:04.965 +This is not some game. + +22 +00:03:05.056 --> 00:03:09.345 +You. I mean we. +we could easily die out here. + +23 +00:03:10.014 --> 00:03:13.959 +Listen. +listen to the sounds of the machine. + +24 +00:03:18.054 --> 00:03:20.009 +Listen to your breathing. + +25 +00:04:27.001 --> 00:04:28.956 +Well. don't you ever get tired of this? + +26 +00:04:29.084 --> 00:04:30.909 +Tired?!? + +27 +00:04:31.126 --> 00:04:34.491 +Emo. the machine is like clockwork. + +28 +00:04:35.083 --> 00:04:37.074 +One move out of place... + +29 +00:04:37.166 --> 00:04:39.121 +...and you're ground to a pulp. + +30 +00:04:40.958 --> 00:04:42.004 +But isn't it - + +31 +00:04:42.041 --> 00:04:46.034 +Pulp. Emo! +Is that what you want. pulp? + +32 +00:04:47.040 --> 00:04:48.995 +Emo. your goal in life... + +33 +00:04:50.081 --> 00:04:51.953 +...pulp? + +34 +00:05:41.156 --> 00:05:43.028 +Emo. close your eyes. + +35 +00:05:44.156 --> 00:05:46.027 +Why? +- Now! + +36 +00:05:51.155 --> 00:05:52.102 +Ok. + +37 +00:05:53.113 --> 00:05:54.688 +Good. + +38 +00:05:59.070 --> 00:06:02.103 +What do you see at your left side. Emo? + +39 +00:06:04.028 --> 00:06:05.899 +Nothing. +- Really? + +40 +00:06:06.027 --> 00:06:07.105 +No. nothing at all. + +41 +00:06:07.944 --> 00:06:11.984 +And at your right. +what do you see at your right side. Emo? + +42 +00:06:13.151 --> 00:06:16.102 +The same Proog. exactly the same... + +43 +00:06:16.942 --> 00:06:19.098 +...nothing! +- Great. + +44 +00:06:40.105 --> 00:06:42.724 +Listen Proog! Do you hear that! + +45 +00:06:43.105 --> 00:06:44.894 +Can we go here? + +46 +00:06:44.979 --> 00:06:47.894 +There? +It isn't safe. Emo. + +47 +00:06:49.145 --> 00:06:52.013 +But... +- Trust me. it's not. + +48 +00:06:53.020 --> 00:06:54.145 +Maybe I could... + +49 +00:06:54.181 --> 00:06:55.969 +No. + +50 +00:06:57.102 --> 00:06:59.934 +NO! + +51 +00:07:00.144 --> 00:07:03.058 +Any further questions. Emo? + +52 +00:07:03.976 --> 00:07:05.090 +No. + +53 +00:07:09.059 --> 00:07:10.089 +Emo? + +54 +00:07:11.142 --> 00:07:13.058 +Emo. why... + +55 +00:07:13.095 --> 00:07:14.022 +Emo... + +56 +00:07:14.058 --> 00:07:18.003 +...why can't you see +the beauty of this place? + +57 +00:07:18.141 --> 00:07:20.048 +The way it works. + +58 +00:07:20.140 --> 00:07:23.895 +How perfect it is. + +59 +00:07:23.932 --> 00:07:26.964 +No. Proog. I don't see. + +60 +00:07:27.056 --> 00:07:29.970 +I don't see because there's nothing there. + +61 +00:07:31.055 --> 00:07:34.965 +And why should I trust my +life to something that isn't there? + +62 +00:07:35.055 --> 00:07:36.926 +Well can you tell me that? + +63 +00:07:37.054 --> 00:07:38.926 +Answer me! + +64 +00:07:42.970 --> 00:07:44.000 +Proog... + +65 +00:07:45.053 --> 00:07:46.985 +...you're a sick man! + +66 +00:07:47.022 --> 00:07:48.918 +Stay away from me! + +67 +00:07:52.052 --> 00:07:54.884 +No! Emo! It's a trap! + +68 +00:07:55.135 --> 00:07:56.931 +Hah. it's a trap. + +69 +00:07:56.968 --> 00:08:01.043 +At the left side you can see +the hanging gardens of Babylon! + +70 +00:08:01.967 --> 00:08:03.957 +How's that for a trap? + +71 +00:08:05.050 --> 00:08:06.922 +No. Emo. + +72 +00:08:09.008 --> 00:08:12.088 +At the right side you can see... +...well guess what... + +73 +00:08:12.924 --> 00:08:14.665 +...the colossus of Rhodes! + +74 +00:08:15.132 --> 00:08:16.053 +No! + +75 +00:08:16.090 --> 00:08:21.919 +The colossus of Rhodes +and it is here just for you Proog. + +76 +00:08:51.001 --> 00:08:52.923 +It is there... + +77 +00:08:52.959 --> 00:08:56.040 +I'm telling you. +Emo... + +78 +00:08:57.000 --> 00:08:59.867 +...it is. \ No newline at end of file diff --git a/docs/examples/elephantsdream/captions.ja.vtt b/docs/examples/elephantsdream/captions.ja.vtt new file mode 100644 index 0000000000..4058648e10 --- /dev/null +++ b/docs/examples/elephantsdream/captions.ja.vtt @@ -0,0 +1,326 @@ +WEBVTT + +1 +00:00:15.042 --> 00:00:18.042 +左に見えるのは… + +2 +00:00:18.750 --> 00:00:20.333 +右に見えるのは… + +3 +00:00:20.417 --> 00:00:21.917 +…首刈り機 + +4 +00:00:22.000 --> 00:00:24.625 +すべて安全 +完璧に安全だ + +5 +00:00:26.333 --> 00:00:27.333 +イーモ? + +6 +00:00:28.875 --> 00:00:30.250 +危ない! + +7 +00:00:47.125 --> 00:00:48.250 +ケガはないか? + +8 +00:00:51.917 --> 00:00:53.917 +ええ、多分… +あなたは? + +9 +00:00:55.625 --> 00:00:57.125 +わしは平気だ + +10 +00:00:57.583 --> 00:01:01.667 +起きてくれイーモ +ここは危ない + +11 +00:01:02.208 --> 00:01:03.667 +行こう + +12 +00:01:03.750 --> 00:01:04.917 +どこに? + +13 +00:01:05.875 --> 00:01:07.875 +すぐにわかるさ! + +14 +00:01:16.167 --> 00:01:18.375 +イーモ、こっちだ + +15 +00:01:34.958 --> 00:01:36.958 +ついて来るんだ! + +16 +00:02:11.583 --> 00:02:12.792 +イーモ、早く! + +17 +00:02:48.375 --> 00:02:50.083 +むやみにさわるな! + +18 +00:02:50.750 --> 00:02:54.500 +僕はただ、電話に +…出ようと + +19 +00:02:55.000 --> 00:02:58.208 +イーモ、見るんだ… +いや、聞いてくれ + +20 +00:02:59.750 --> 00:03:02.292 +君は「聞き方」を知る必要がある + +21 +00:03:03.625 --> 00:03:05.125 +これは遊びじゃない + +22 +00:03:06.167 --> 00:03:10.417 +我々はここでは +たやすく死ぬ + +23 +00:03:11.208 --> 00:03:14.125 +機械の声を聞くんだ + +24 +00:03:18.333 --> 00:03:22.417 +君の息づかいを聞くんだ + +25 +00:04:27.208 --> 00:04:29.250 +そんなことして疲れない? + +26 +00:04:29.583 --> 00:04:31.083 +疲れる?! + +27 +00:04:31.750 --> 00:04:34.667 +この機械は非常に正確で + +28 +00:04:35.500 --> 00:04:37.708 +一つ間違えば… + +29 +00:04:37.833 --> 00:04:40.792 +…地面に落ちてバラバラだ + +30 +00:04:41.042 --> 00:04:42.375 +え、でも― + +31 +00:04:42.417 --> 00:04:46.542 +バラバラだぞ、イーモ! +それでいいのか? + +32 +00:04:48.083 --> 00:04:50.000 +バラバラで死ぬんだぞ? + +33 +00:04:50.583 --> 00:04:52.250 +バラバラだ! + +34 +00:05:41.833 --> 00:05:43.458 +イーモ、目を閉じるんだ + +35 +00:05:44.917 --> 00:05:46.583 +なぜ? +―早く! + +36 +00:05:53.750 --> 00:05:56.042 +それでいい + +37 +00:05:59.542 --> 00:06:03.792 +左に見えるものは何だ、イーモ? + +38 +00:06:04.417 --> 00:06:06.000 +え…何も +―本当か? + +39 +00:06:06.333 --> 00:06:07.917 +全く何も + +40 +00:06:08.042 --> 00:06:12.833 +では右は +何か見えるか、イーモ? + +41 +00:06:13.875 --> 00:06:16.917 +同じだよプルーグ、全く同じ… + +42 +00:06:17.083 --> 00:06:18.583 +何もない! + +43 +00:06:40.625 --> 00:06:43.208 +プルーグ!何か聞こえない? + +44 +00:06:43.625 --> 00:06:45.042 +あそこに行かないか? + +45 +00:06:45.208 --> 00:06:48.042 +あそこ? +…安全じゃない + +46 +00:06:49.917 --> 00:06:52.500 +でも… +―本当に危ないぞ + +47 +00:06:53.292 --> 00:06:54.792 +大丈夫だよ… + +48 +00:06:54.833 --> 00:06:56.333 +だめだ + +49 +00:06:57.667 --> 00:07:00.167 +だめだ! + +50 +00:07:00.875 --> 00:07:03.750 +まだ続ける気か、イーモ? + +51 +00:07:04.250 --> 00:07:05.917 +いいえ… + +52 +00:07:09.458 --> 00:07:10.833 +イーモ? + +53 +00:07:11.875 --> 00:07:13.542 +イーモ、なぜ… + +54 +00:07:13.583 --> 00:07:14.458 +イーモ… + +55 +00:07:14.500 --> 00:07:18.500 +…なぜここの美しさが +見えない? + +56 +00:07:18.833 --> 00:07:20.750 +仕組みがこんなに… + +57 +00:07:20.875 --> 00:07:24.000 +こんなに完全なのに + +58 +00:07:24.083 --> 00:07:27.417 +もういいよ!プルーグ! + +59 +00:07:27.542 --> 00:07:30.333 +そこには何もないんだから + +60 +00:07:31.500 --> 00:07:35.333 +なぜ命を「ない」物に +ゆだねなきゃ? + +61 +00:07:35.583 --> 00:07:37.125 +教えてくれないか? + +62 +00:07:37.500 --> 00:07:39.167 +さあ! + +63 +00:07:43.208 --> 00:07:44.583 +プルーグ… + +64 +00:07:45.500 --> 00:07:47.333 +あなたは病気なんだ + +65 +00:07:47.375 --> 00:07:49.208 +僕から離れてくれ + +66 +00:07:52.583 --> 00:07:55.083 +いかん!イーモ!ワナだ! + +67 +00:07:55.833 --> 00:07:57.167 +ワナだ? ふーん + +68 +00:07:57.208 --> 00:08:01.750 +左に何が見える? +バビロンの空中庭園! + +69 +00:08:02.250 --> 00:08:04.292 +これがワナとでも? + +70 +00:08:05.458 --> 00:08:07.125 +だめだ、イーモ + +71 +00:08:09.417 --> 00:08:12.792 +右にあるのは… +…すごい!… + +72 +00:08:13.000 --> 00:08:14.750 +…ロードス島の巨像だ! + +73 +00:08:15.833 --> 00:08:16.708 +やめろ! + +74 +00:08:16.750 --> 00:08:22.167 +この巨像はあなたの物 +プルーグ、あなたのだよ + +75 +00:08:51.333 --> 00:08:53.167 +いってるじゃないか… + +76 +00:08:53.208 --> 00:08:55.500 +そこにあるって、イーモ… + +77 +00:08:57.333 --> 00:09:00.000 +…あるって \ No newline at end of file diff --git a/docs/examples/elephantsdream/captions.ru.vtt b/docs/examples/elephantsdream/captions.ru.vtt new file mode 100644 index 0000000000..aee7e49f33 --- /dev/null +++ b/docs/examples/elephantsdream/captions.ru.vtt @@ -0,0 +1,356 @@ +WEBVTT + +1 +00:00:14.958 --> 00:00:17.833 +Слева мы видим... + +2 +00:00:18.458 --> 00:00:20.208 +справа мы видим... + +3 +00:00:20.333 --> 00:00:21.875 +...голово-клацов. + +4 +00:00:22.000 --> 00:00:24.583 +всё в порядке. +в полном порядке. + +5 +00:00:26.333 --> 00:00:27.333 +Имо? + +6 +00:00:28.833 --> 00:00:30.250 +Осторожно! + +7 +00:00:47.125 --> 00:00:48.250 +Ты не ранен? + +8 +00:00:51.875 --> 00:00:53.875 +Вроде нет... +а ты? + +9 +00:00:55.583 --> 00:00:57.125 +Я в порядке. + +10 +00:00:57.542 --> 00:01:01.625 +Вставай. +Имо. здесь не безопасно. + +11 +00:01:02.208 --> 00:01:03.625 +Пойдём. + +12 +00:01:03.708 --> 00:01:05.708 +Что дальше? + +13 +00:01:05.833 --> 00:01:07.833 +Ты увидишь! + +14 +00:01:08.000 --> 00:01:08.833 +Ты увидишь... + +15 +00:01:16.167 --> 00:01:18.375 +Имо. сюда. + +16 +00:01:34.917 --> 00:01:35.750 +За мной! + +17 +00:02:11.542 --> 00:02:12.750 +Имо. быстрее! + +18 +00:02:48.375 --> 00:02:50.083 +Ты не обращаешь внимания! + +19 +00:02:50.708 --> 00:02:54.500 +Я только хотел ответить на ... +...звонок. + +20 +00:02:55.000 --> 00:02:58.208 +Имо. смотри. +то есть слушай... + +21 +00:02:59.708 --> 00:03:02.292 +Ты должен учиться слушать. + +22 +00:03:03.250 --> 00:03:05.333 +Это не какая-нибудь игра. + +23 +00:03:06.000 --> 00:03:08.833 +Ты. вернее мы. легко можем погибнуть здесь. + +24 +00:03:10.000 --> 00:03:11.167 +Слушай... + +25 +00:03:11.667 --> 00:03:14.125 +слушай звуки машины. + +26 +00:03:18.333 --> 00:03:20.417 +Слушай своё дыхание. + +27 +00:04:27.208 --> 00:04:29.250 +И не надоест тебе это? + +28 +00:04:29.542 --> 00:04:31.083 +Надоест?!? + +29 +00:04:31.708 --> 00:04:34.625 +Имо! Машина - +она как часовой механизм. + +30 +00:04:35.500 --> 00:04:37.667 +Одно движение не туда... + +31 +00:04:37.792 --> 00:04:39.750 +...и тебя размелют в месиво! + +32 +00:04:41.042 --> 00:04:42.375 +А разве это не - + +33 +00:04:42.417 --> 00:04:46.500 +Месиво. Имо! +ты этого хочешь? месиво? + +34 +00:04:48.083 --> 00:04:50.000 +Имо. твоя цель в жизни? + +35 +00:04:50.542 --> 00:04:52.250 +Месиво! + +36 +00:05:41.792 --> 00:05:43.458 +Имо. закрой глаза. + +37 +00:05:44.875 --> 00:05:46.542 +Зачем? +- Ну же! + +38 +00:05:51.500 --> 00:05:52.333 +Ладно. + +39 +00:05:53.708 --> 00:05:56.042 +Хорошо. + +40 +00:05:59.500 --> 00:06:02.750 +Что ты видишь слева от себя. Имо? + +41 +00:06:04.417 --> 00:06:06.000 +Ничего. +- Точно? + +42 +00:06:06.333 --> 00:06:07.875 +да. совсем ничего. + +43 +00:06:08.042 --> 00:06:12.708 +А справа от себя. +что ты видишь справа от себя. Имо? + +44 +00:06:13.833 --> 00:06:16.875 +Да то же Пруг. в точности то же... + +45 +00:06:17.042 --> 00:06:18.500 +Ничего! + +46 +00:06:18.667 --> 00:06:19.500 +Прекрасно... + +47 +00:06:40.583 --> 00:06:42.917 +Прислушайся. Пруг! Ты слышишь это? + +48 +00:06:43.583 --> 00:06:45.042 +Может. мы пойдём туда? + +49 +00:06:45.208 --> 00:06:48.042 +Туда? +Это не безопасно. Имо. + +50 +00:06:49.875 --> 00:06:52.500 +Но... +- Поверь мне. это так. + +51 +00:06:53.292 --> 00:06:54.750 +Может я бы ... + +52 +00:06:54.792 --> 00:06:56.333 +Нет. + +53 +00:06:57.625 --> 00:06:59.583 +- Но... +- НЕТ! + +54 +00:06:59.708 --> 00:07:00.833 +Нет! + +55 +00:07:00.833 --> 00:07:03.708 +Ещё вопросы. Имо? + +56 +00:07:04.250 --> 00:07:05.875 +Нет. + +57 +00:07:09.458 --> 00:07:10.792 +Имо? + +58 +00:07:11.833 --> 00:07:13.500 +Имо. почему... + +59 +00:07:13.542 --> 00:07:14.458 +Имо... + +60 +00:07:14.500 --> 00:07:18.500 +...почему? почему ты не видишь +красоты этого места? + +61 +00:07:18.792 --> 00:07:20.708 +То как оно работает. + +62 +00:07:20.833 --> 00:07:24.000 +Как совершенно оно. + +63 +00:07:24.083 --> 00:07:27.417 +Нет. Пруг. я не вижу. + +64 +00:07:27.500 --> 00:07:30.333 +Я не вижу. потому что здесь ничего нет. + +65 +00:07:31.375 --> 00:07:35.333 +И почему я должен доверять свою жизнь +чему-то. чего здесь нет? + +66 +00:07:35.542 --> 00:07:37.125 +это ты мне можешь сказать? + +67 +00:07:37.500 --> 00:07:39.167 +Ответь мне! + +68 +00:07:43.208 --> 00:07:44.542 +Пруг... + +69 +00:07:45.500 --> 00:07:47.333 +Ты просто больной! + +70 +00:07:47.375 --> 00:07:48.500 +Отстань от меня. + +71 +00:07:48.625 --> 00:07:49.917 +Имо... + +72 +00:07:52.542 --> 00:07:55.083 +Нет! Имо! Это ловушка! + +73 +00:07:55.792 --> 00:07:57.167 +Это ловушка! + +74 +00:07:57.208 --> 00:08:01.708 +Слева от себя вы можете увидеть +Висящие сады Семирамиды! + +75 +00:08:02.250 --> 00:08:04.292 +Сойдёт за ловушку? + +76 +00:08:05.458 --> 00:08:07.125 +Нет. Имо. + +77 +00:08:09.417 --> 00:08:12.750 +Справа от себя вы можете увидеть... +...угадай кого... + +78 +00:08:13.000 --> 00:08:14.708 +...Колосса Родосского! + +79 +00:08:15.500 --> 00:08:16.625 +Нет! + +80 +00:08:16.667 --> 00:08:21.125 +Колосс Родосский! +И он здесь специально для тебя. Пруг. + +81 +00:08:21.167 --> 00:08:22.208 +Специально для тебя... + +82 +00:08:51.333 --> 00:08:53.167 +Она здесь есть! + +83 +00:08:53.208 --> 00:08:55.500 +Говорю тебе. +Имо... + +84 +00:08:57.333 --> 00:09:00.000 +...она есть... есть... \ No newline at end of file diff --git a/docs/examples/elephantsdream/captions.sv.vtt b/docs/examples/elephantsdream/captions.sv.vtt new file mode 100644 index 0000000000..6666eedfbc --- /dev/null +++ b/docs/examples/elephantsdream/captions.sv.vtt @@ -0,0 +1,349 @@ +WEBVTT + +1 +00:00:15.042 --> 00:00:18.250 +Till vänster kan vi se... +Ser vi... + +2 +00:00:18.708 --> 00:00:20.333 +Till höger ser vi... + +3 +00:00:20.417 --> 00:00:21.958 +...huvudkaparna. + +4 +00:00:22.000 --> 00:00:24.792 +Allt är säkert. +alldeles ofarligt. + +5 +00:00:24.917 --> 00:00:26.833 +Emo? + +6 +00:00:28.750 --> 00:00:30.167 +Se upp! + +7 +00:00:46.708 --> 00:00:48.750 +Är du skadad? + +8 +00:00:51.875 --> 00:00:54.458 +Jag tror inte det... +Är du? + +9 +00:00:55.292 --> 00:00:57.333 +Jag är ok. + +10 +00:00:57.542 --> 00:01:01.625 +Res dig upp Emo. +Det är inte säkert här. + +11 +00:01:02.208 --> 00:01:03.625 +Kom så går vi. + +12 +00:01:03.708 --> 00:01:05.708 +Vad nu då? + +13 +00:01:05.833 --> 00:01:07.833 +Du får se... + +14 +00:01:08.042 --> 00:01:10.417 +Du får se. + +15 +00:01:15.958 --> 00:01:18.375 +Emo. den här vägen. + +16 +00:01:34.417 --> 00:01:36.750 +Följ efter mig! + +17 +00:02:11.250 --> 00:02:13.250 +Skynda dig. Emo! + +18 +00:02:48.375 --> 00:02:50.583 +Du är inte uppmärksam! + +19 +00:02:50.708 --> 00:02:54.500 +Jag vill bara svara... +... i telefonen. + +20 +00:02:54.500 --> 00:02:58.208 +Emo. se här... +Lyssna menar jag. + +21 +00:02:59.708 --> 00:03:02.292 +Du måste lära dig att lyssna. + +22 +00:03:03.292 --> 00:03:05.208 +Det här är ingen lek. + +23 +00:03:05.250 --> 00:03:08.917 +Du... Jag menar vi. +vi skulle kunna dö här ute. + +24 +00:03:09.917 --> 00:03:11.417 +Lyssna... + +25 +00:03:11.708 --> 00:03:14.833 +Lyssna på ljuden från maskinen. + +26 +00:03:18.125 --> 00:03:21.417 +Lyssna på dina andetag. + +27 +00:04:26.625 --> 00:04:29.250 +Tröttnar du aldrig på det här? + +28 +00:04:29.542 --> 00:04:31.083 +Tröttnar!? + +29 +00:04:31.208 --> 00:04:33.458 +Emo. maskinen är som... + +30 +00:04:33.458 --> 00:04:35.333 +Som ett urverk. + +31 +00:04:35.417 --> 00:04:37.167 +Ett felsteg... + +32 +00:04:37.208 --> 00:04:39.750 +...och du blir krossad. + +33 +00:04:41.042 --> 00:04:42.292 +Men är det inte - + +34 +00:04:42.292 --> 00:04:47.000 +Krossad. Emo! +Är det vad du vill bli? Krossad till mos? + +35 +00:04:47.500 --> 00:04:50.542 +Emo. är det ditt mål i livet? + +36 +00:04:50.667 --> 00:04:53.250 +Att bli mos!? + +37 +00:05:41.375 --> 00:05:43.458 +Emo. blunda. + +38 +00:05:44.375 --> 00:05:46.542 +Varför då? +- Blunda! + +39 +00:05:51.292 --> 00:05:55.042 +Ok. +- Bra. + +40 +00:05:59.500 --> 00:06:02.750 +Vad ser du till vänster om dig Emo? + +41 +00:06:04.125 --> 00:06:06.292 +Ingenting. +- Säker? + +42 +00:06:06.333 --> 00:06:07.958 +Ingenting alls. + +43 +00:06:08.042 --> 00:06:12.625 +Jaså. och till höger om dig... +Vad ser du där. Emo? + +44 +00:06:13.750 --> 00:06:15.583 +Samma där Proog... + +45 +00:06:15.583 --> 00:06:18.083 +Exakt samma där. ingenting! + +46 +00:06:18.083 --> 00:06:19.667 +Perfekt. + +47 +00:06:40.500 --> 00:06:42.917 +Lyssna Proog! Hör du? + +48 +00:06:43.500 --> 00:06:45.125 +Kan vi gå dit? + +49 +00:06:45.208 --> 00:06:48.125 +Gå dit? +Det är inte tryggt. + +50 +00:06:49.583 --> 00:06:52.583 +Men. men... +- Tro mig. det inte säkert. + +51 +00:06:53.000 --> 00:06:54.292 +Men kanske om jag - + +52 +00:06:54.292 --> 00:06:56.333 +Nej. + +53 +00:06:57.208 --> 00:07:00.167 +Men - +- Nej. NEJ! + +54 +00:07:00.917 --> 00:07:03.792 +Några fler frågor Emo? + +55 +00:07:04.250 --> 00:07:05.875 +Nej. + +56 +00:07:09.542 --> 00:07:11.375 +Emo? +- Ja? + +57 +00:07:11.542 --> 00:07:15.667 +Emo. varför... + +58 +00:07:15.792 --> 00:07:18.583 +Varför kan du inte se skönheten i det här? + +59 +00:07:18.792 --> 00:07:21.708 +Hur det fungerar. + +60 +00:07:21.833 --> 00:07:24.000 +Hur perfekt det är. + +61 +00:07:24.083 --> 00:07:27.333 +Nej Proog. jag kan inte se det. + +62 +00:07:27.333 --> 00:07:30.333 +Jag ser det inte. för det finns inget där. + +63 +00:07:31.292 --> 00:07:35.333 +Och varför skulle jag lägga mitt liv +i händerna på något som inte finns? + +64 +00:07:35.333 --> 00:07:37.083 +Kan du berätta det för mig? +- Emo... + +65 +00:07:37.083 --> 00:07:39.167 +Svara mig! + +66 +00:07:43.500 --> 00:07:45.208 +Proog... + +67 +00:07:45.208 --> 00:07:47.083 +Du är inte frisk! + +68 +00:07:47.167 --> 00:07:49.292 +Håll dig borta från mig! + +69 +00:07:52.292 --> 00:07:55.083 +Nej! Emo! +Det är en fälla! + +70 +00:07:55.375 --> 00:07:57.208 +Heh. det är en fälla. + +71 +00:07:57.208 --> 00:08:01.708 +På vänster sida ser vi... +Babylons hängande trädgårdar! + +72 +00:08:01.958 --> 00:08:04.000 +Vad sägs om den fällan? + +73 +00:08:05.458 --> 00:08:07.333 +Nej. Emo. + +74 +00:08:08.917 --> 00:08:12.667 +Till höger ser vi... +Gissa! + +75 +00:08:12.750 --> 00:08:15.125 +Rhodos koloss! + +76 +00:08:15.375 --> 00:08:16.500 +Nej! + +77 +00:08:16.500 --> 00:08:20.250 +Kolossen på Rhodos! +Och den är här för din skull. Proog... + +78 +00:08:20.250 --> 00:08:23.250 +Bara för din skull. + +79 +00:08:50.917 --> 00:08:53.250 +Den är där... + +80 +00:08:53.625 --> 00:08:56.417 +Tro mig. +Emo... + +81 +00:08:57.000 --> 00:09:00.000 +Det är den. +Det är den... \ No newline at end of file diff --git a/docs/examples/elephantsdream/chapters.en.vtt b/docs/examples/elephantsdream/chapters.en.vtt new file mode 100644 index 0000000000..9740a4130e --- /dev/null +++ b/docs/examples/elephantsdream/chapters.en.vtt @@ -0,0 +1,44 @@ +WEBVTT + +NOTE Created by Owen Edwards 2015. http://creativecommons.org/licenses/by/2.5/ +NOTE Based on 'finalbreakdown.rtf', part of the prepoduction notes, which are: +NOTE (c) Copyright 2006, Blender Foundation / +NOTE Netherlands Media Art Institute / +NOTE www.elephantsdream.org + +1 +00:00:00.000 --> 00:00:27.500 +Prologue + +2 +00:00:27.500 --> 00:01:10.000 +Switchboard trap + +3 +00:01:10.000 --> 00:03:25.000 +Telephone/Lecture + +4 +00:03:25.000 --> 00:04:52.000 +Typewriter + +5 +00:04:52.000 --> 00:06:19.500 +Proog shows Emo stuff + +6 +00:06:19.500 --> 00:07:09.000 +Which way + +7 +00:07:09.000 --> 00:07:45.000 +Emo flips out + +8 +00:07:45.000 --> 00:09:25.000 +Emo creates + +9 +00:09:25.000 --> 00:10:53.000 +Closing credits + diff --git a/docs/examples/elephantsdream/descriptions.en.vtt b/docs/examples/elephantsdream/descriptions.en.vtt new file mode 100644 index 0000000000..8835b7009a --- /dev/null +++ b/docs/examples/elephantsdream/descriptions.en.vtt @@ -0,0 +1,280 @@ +WEBVTT +License: CC BY 4.0 http://creativecommons.org/licenses/by/4.0/ +Author: Silvia Pfeiffer + +1 +00:00:00.000 --> 00:00:05.000 +The orange open movie project presents + +2 +00:00:05.010 --> 00:00:12.000 +Introductory titles are showing on the background of a water pool with fishes swimming and mechanical objects lying on a stone floor. + +3 +00:00:12.010 --> 00:00:14.800 +elephants dream + +4 +00:00:26.100 --> 00:00:28.206 +Two people stand on a small bridge. + +5 +00:00:30.010 --> 00:00:40.000 +The old man, Proog, shoves the younger and less experienced Emo on the ground to save him from being mowed down by a barrage of jack plugs that whir back and forth between the two massive switch-board-like walls. + +6 +00:00:40.000 --> 00:00:47.000 +The plugs are oblivious of the two, endlessly channeling streams of bizarre sounds and data. + +7 +00:00:48.494 --> 00:00:51.994 +Emo sits on the bridge and checks his limbs. + +8 +00:01:09.150 --> 00:01:16.030 +After the squealing plugs move on, Proog makes sure that Emo is unharmed and urges him onwards through a crack in one of the plug-walls. + +9 +00:01:18.050 --> 00:01:24.000 +They walk through the narrow hall into a massive room that fades away into blackness on all sides. + +10 +00:01:24.050 --> 00:01:34.200 +Only one path is visible, suspended in mid-air that runs between thousands of dangling electric cables on which sit crowds of robin-like robotic birds. + +11 +00:01:36.000 --> 00:01:40.000 +As Proog and Emo enter the room, the birds begin to wake up and notice them. + +12 +00:01:42.000 --> 00:01:50.000 +Realizing the danger, Proog grabs Emo by the arm. + +13 +00:01:50.050 --> 00:02:00.000 +They run along the increasingly bizarre path as the birds begin to swarm. + +14 +00:02:00.050 --> 00:02:11.000 +All sound is blocked out by the birds which are making the same noises as the jack-plugs, garbled screaming and obscure sentences and static. + +15 +00:02:12.600 --> 00:02:17.000 +The path dead-ends, stopping in the middle of no-where above the infinite drop. + +16 +00:02:17.600 --> 00:02:22.000 +Proog turns around as the birds reach them and begin to dive-bomb at them. + +17 +00:02:22.600 --> 00:02:28.000 +At the last moment, Proog takes out an old candlestick phone and the birds dive into the speaker piece. + +18 +00:02:28.600 --> 00:02:31.000 +The screen cuts to black. + +19 +00:02:31.600 --> 00:02:38.000 +In the next scene, Proog stands at one end of a room, suspiciously watching what is probably the same candlestick phone, which is ringing. + +20 +00:02:38.500 --> 00:02:41.000 +Emo watches from the other side of the room. + +21 +00:02:41.500 --> 00:02:43.000 +The phone continues to ring. + +22 +00:02:43.500 --> 00:02:48.000 +After a while Emo approaches it to answer it, but Proog slaps his hand away. + +23 +00:02:57.972 --> 00:02:59.100 +Proog takes the ear-piece off the hook. + +24 +00:03:13.500 --> 00:03:18.054 +The phone speaker revealed a mass of clawed, fleshy polyps which scream and gibber obscenely. + +25 +00:03:25.000 --> 00:03:33.000 +There is a solemn silence as Emo looks around the room and the technical objects therein. + +26 +00:03:38.000 --> 00:03:44.000 +Emo laughs disbelievingly and Proog walks away. + +27 +00:03:46.000 --> 00:03:54.000 +In the next scene, the two enter another massive black room. + +28 +00:03:54.500 --> 00:04:04.000 +There is no path, the entry platform is the only structure that seems to be there except for another exit, lit distantly at the far side. + +29 +00:04:04.500 --> 00:04:14.000 +Proog takes a step forward into the void, and his feet are suddenly caught by giant typewriter arms that rocket up out of the blackness to catch his feet as he dances across mid-air. + +30 +00:04:14.500 --> 00:04:22.000 +Emo follows Proog with somewhat less enthusiasm as the older man leads the way. + +31 +00:04:52.000 --> 00:04:58.000 +They reach the end of the room and go through a hall into a small compartment. + +32 +00:05:02.000 --> 00:05:06.000 +Proog presses a button, and the door shuts. + +33 +00:05:06.500 --> 00:05:09.000 +It is an elevator. + +34 +00:05:09.500 --> 00:05:24.000 +The elevator lurches suddenly as it is grabbed by a giant mechanical arm and thrown upwards, rushing up through an ever-widening tunnel. + +35 +00:05:26.500 --> 00:05:32.000 +When it begins to slow down, another arm grabs the capsule and throws it even further up. + +36 +00:05:32.500 --> 00:05:40.000 +As it moves up, the walls unlock and fall away, leaving only the floor with the two on it, rushing higher and higher. + +37 +00:05:54.500 --> 00:05:59.000 +They exit the tunnel into a black sky and the platform reaches the peak of its arc. + +38 +00:06:19.500 --> 00:06:26.000 +The elevator begins to drop down another shaft, coming to rest as it slams into the floor of another room and bringing the two to a level stop. + +39 +00:06:26.500 --> 00:06:28.000 +A camera flashes. + +40 +00:06:28.010 --> 00:06:34.000 +They are in a large, dingy room filled with strange, generator-like devices and dotted with boxy holographic projectors. + +41 +00:06:34.500 --> 00:06:38.000 +One of them is projecting a portion of wall with a door in it right beside them. + +42 +00:06:38.500 --> 00:06:40.000 +The door seems harmless enough. + +43 +00:06:42.800 --> 00:06:45.100 +From behind the door comes light music. + +44 +00:06:56.000 --> 00:07:00.100 +Proog presses a button on his cane, which changes the holograph to another wall. + +45 +00:07:05.100 --> 00:07:11.000 +Proog finishes the wall, and boxes them into a Safe Room, out of the view of anything outside. + +46 +00:07:39.000 --> 00:07:42.500 +Proog slaps him, trying to bring him to his senses. + +47 +00:07:45.000 --> 00:07:52.000 +Emo storms away down the length of the room towards a wall he apparently cannot see and the wall begins to move, extending the length of the room. + +48 +00:08:00.000 --> 00:08:07.000 +The walls begin to discolour and mechanical roots start tearing through the walls to his left. + +49 +00:08:07.010 --> 00:08:09.000 +The roots move forwards toward Proog. + +50 +00:08:22.000 --> 00:08:31.000 +The rest of the safety wall crumples away as a pair of massive hands heave out of the ground and begin to attack. + +51 +00:08:31.010 --> 00:08:37.000 +Proog is knocked down by the shockwave, while Emo turns and begins to walk away, waving his finger around his temple in the 'crazy' sign. + +52 +00:08:37.010 --> 00:08:44.000 +In a last effort, Proog extricates himself from the tentacle roots, and cracks Emo over the back of the head with his cane. + +53 +00:08:44.500 --> 00:08:51.000 +As Emo collapses, everything falls away, and Proog and Emo are left in one tiny patch of light in the middle of blackness. + +54 +00:09:00.000 --> 00:09:20.000 +The scene fades to black while panning over a pile of tentacle roots lying on the ground. + +55 +00:09:26.000 --> 00:09:28.000 +Credits begin: + +56 +00:09:28.500 --> 00:09:35.000 +Orange Open Movie Team +Director: Bassum Kurdali +Art Director: Andreas Goralczyk + +57 +00:09:35.500 --> 00:09:39.000 +Music and Sound Design: Jan Morgenstern + +58 +00:09:39.500 --> 00:09:44.000 +Emo: Cas Jansen +Proog: Tygo Gernandt + +59 +00:09:44.500 --> 00:09:50.000 +Screenplay: Pepijn Zwanenberg +Original Concept & Scenario: Andreas Goralczyk, Bassam Kurdali, Ton Roosendaal + +60 +00:09:50.500 --> 00:10:24.000 +More people for +Additional Artwork and Animation +Texture Photography +Software Development +3D Modelling, Animation, Rendering, Compiling Software +Special Thanks to Open Source Projects +Rendering Services Provided +Hardware Sponsored +Casting +Sound FX, Foley, Dialogue Editing, Audio Mix and Post +Voice Recording +HDCam conversion +Netherlands Media Art Institute Staff +Blender Foundation Staff + +61 +00:10:24.500 --> 00:10:30.000 +Many Thanks to our Donation and DVD sponsors + +62 +00:10:30.500 --> 00:10:47.000 +Elephants Dream has been realised with financial support from +The Netherlands Film Fund +Mondriaan Foundation +VSBfonds +Uni-Verse / EU Sixth Framework Programme + +63 +00:10:47.500 --> 00:10:53.000 +Produced By +Ton Roosendaal +Copyright 2006 +Netherlands Media Art Institute / Montevideo +Blender Foundation diff --git a/docs/examples/elephantsdream/index.html b/docs/examples/elephantsdream/index.html new file mode 100644 index 0000000000..09dd90b61d --- /dev/null +++ b/docs/examples/elephantsdream/index.html @@ -0,0 +1,46 @@ + + + + + Video.js Text Descriptions, Chapters & Captions Example + + + + + + + + + + +

This page demonstrates a text descriptions track (intended primarily for blind and visually impaired consumers of visual media)

+ + + + + diff --git a/lang/en.json b/lang/en.json index ea90fda185..1d74aabf51 100644 --- a/lang/en.json +++ b/lang/en.json @@ -18,6 +18,8 @@ "Captions": "Captions", "captions off": "captions off", "Chapters": "Chapters", + "Descriptions": "Descriptions", + "descriptions off": "descriptions off", "You aborted the media playback": "You aborted the media playback", "A network error caused the media download to fail part-way.": "A network error caused the media download to fail part-way.", "The media could not be loaded, either because the server or network failed or because the format is not supported.": "The media could not be loaded, either because the server or network failed or because the format is not supported.", @@ -30,5 +32,6 @@ "This modal can be closed by pressing the Escape key or activating the close button.": "This modal can be closed by pressing the Escape key or activating the close button.", ", opens captions settings dialog": ", opens captions settings dialog", ", opens subtitles settings dialog": ", opens subtitles settings dialog", + ", opens descriptions settings dialog": ", opens descriptions settings dialog", ", selected": ", selected" -} \ No newline at end of file +} diff --git a/sandbox/descriptions.html.example b/sandbox/descriptions.html.example new file mode 100644 index 0000000000..c12c2c03e0 --- /dev/null +++ b/sandbox/descriptions.html.example @@ -0,0 +1,43 @@ + + + + + Video.js Text Descriptions, Chapters & Captions Example + + + + + + + + + + + + + + + + + diff --git a/src/css/components/_descriptions.scss b/src/css/components/_descriptions.scss new file mode 100644 index 0000000000..d298ef8205 --- /dev/null +++ b/src/css/components/_descriptions.scss @@ -0,0 +1,3 @@ +.video-js .vjs-descriptions-button { + @extend .vjs-icon-audio-description; +} diff --git a/src/css/components/_layout.scss b/src/css/components/_layout.scss index 14f2c2f52e..632325b379 100644 --- a/src/css/components/_layout.scss +++ b/src/css/components/_layout.scss @@ -124,6 +124,11 @@ body.vjs-full-window { // Hide disabled or unsupported controls. .vjs-hidden { display: none !important; } +.vjs-disabled { + opacity: 0.5; + cursor: default; +} + // Visually hidden offscreen, but accessible to screen readers. .video-js .vjs-offscreen { height: 1px; diff --git a/src/css/components/menu/_menu.scss b/src/css/components/menu/_menu.scss index c4730c946e..e806f421c0 100644 --- a/src/css/components/menu/_menu.scss +++ b/src/css/components/menu/_menu.scss @@ -2,6 +2,16 @@ cursor: pointer; } +// Change cursor back to default if the menu button is disabled +.vjs-menu-button.vjs-disabled { + cursor: default; +} + +// prevent menus from opening while disabled +.vjs-workinghover .vjs-menu-button.vjs-disabled:hover .vjs-menu { + display: none; +} + .vjs-menu .vjs-menu-content { display: block; padding: 0; margin: 0; diff --git a/src/css/video-js.scss b/src/css/video-js.scss index df1ec520f4..1214f87aaa 100644 --- a/src/css/video-js.scss +++ b/src/css/video-js.scss @@ -37,6 +37,7 @@ @import "components/loading"; @import "components/captions"; @import "components/chapters"; +@import "components/descriptions"; @import "components/subtitles"; @import "components/adaptive"; @import "components/captions-settings"; diff --git a/src/js/clickable-component.js b/src/js/clickable-component.js index cdb0012fda..3ee32f7018 100644 --- a/src/js/clickable-component.js +++ b/src/js/clickable-component.js @@ -129,6 +129,30 @@ class ClickableComponent extends Component { return super.addChild(child, options); } + /** + * Enable the component element + * + * @return {Component} + * @method enable + */ + enable() { + this.removeClass('vjs-disabled'); + this.el_.setAttribute('aria-disabled', 'false'); + return this; + } + + /** + * Disable the component element + * + * @return {Component} + * @method disable + */ + disable() { + this.addClass('vjs-disabled'); + this.el_.setAttribute('aria-disabled', 'true'); + return this; + } + /** * Handle Click - Override with specific functionality for component * diff --git a/src/js/control-bar/control-bar.js b/src/js/control-bar/control-bar.js index df0e4c433c..90601e5e42 100644 --- a/src/js/control-bar/control-bar.js +++ b/src/js/control-bar/control-bar.js @@ -16,6 +16,7 @@ import VolumeControl from './volume-control/volume-control.js'; import VolumeMenuButton from './volume-menu-button.js'; import MuteToggle from './mute-toggle.js'; import ChaptersButton from './text-track-controls/chapters-button.js'; +import DescriptionsButton from './text-track-controls/descriptions-button.js'; import SubtitlesButton from './text-track-controls/subtitles-button.js'; import CaptionsButton from './text-track-controls/captions-button.js'; import PlaybackRateMenuButton from './playback-rate-menu/playback-rate-menu-button.js'; @@ -58,6 +59,7 @@ ControlBar.prototype.options_ = { 'customControlSpacer', 'playbackRateMenuButton', 'chaptersButton', + 'descriptionsButton', 'subtitlesButton', 'captionsButton', 'fullscreenToggle' diff --git a/src/js/control-bar/text-track-controls/descriptions-button.js b/src/js/control-bar/text-track-controls/descriptions-button.js new file mode 100644 index 0000000000..671c620c56 --- /dev/null +++ b/src/js/control-bar/text-track-controls/descriptions-button.js @@ -0,0 +1,77 @@ +/** + * @file descriptions-button.js + */ +import TextTrackButton from './text-track-button.js'; +import Component from '../../component.js'; +import * as Fn from '../../utils/fn.js'; + +/** + * The button component for toggling and selecting descriptions + * + * @param {Object} player Player object + * @param {Object=} options Object of option names and values + * @param {Function=} ready Ready callback function + * @extends TextTrackButton + * @class DescriptionsButton + */ +class DescriptionsButton extends TextTrackButton { + + constructor(player, options, ready){ + super(player, options, ready); + this.el_.setAttribute('aria-label', 'Descriptions Menu'); + + let tracks = player.textTracks(); + + if (tracks) { + let changeHandler = Fn.bind(this, this.handleTracksChange); + + tracks.addEventListener('change', changeHandler); + this.on('dispose', function() { + tracks.removeEventListener('change', changeHandler); + }); + } + } + + /** + * Handle text track change + * + * @method handleTracksChange + */ + handleTracksChange(event){ + let tracks = this.player().textTracks(); + let disabled = false; + + // Check whether a track of a different kind is showing + for (let i = 0, l = tracks.length; i < l; i++) { + let track = tracks[i]; + if (track['kind'] !== this.kind_ && track['mode'] === 'showing') { + disabled = true; + break; + } + } + + // If another track is showing, disable this menu button + if (disabled) { + this.disable(); + } else { + this.enable(); + } + } + + /** + * Allow sub components to stack CSS class names + * + * @return {String} The constructed class name + * @method buildCSSClass + */ + buildCSSClass() { + return `vjs-descriptions-button ${super.buildCSSClass()}`; + } + +} + +DescriptionsButton.prototype.kind_ = 'descriptions'; +DescriptionsButton.prototype.controlText_ = 'Descriptions'; + +Component.registerComponent('DescriptionsButton', DescriptionsButton); +export default DescriptionsButton; diff --git a/src/js/menu/menu-button.js b/src/js/menu/menu-button.js index faa4a27a7e..707bd3d82f 100644 --- a/src/js/menu/menu-button.js +++ b/src/js/menu/menu-button.js @@ -23,7 +23,9 @@ class MenuButton extends ClickableComponent { this.update(); - this.el_.setAttribute('aria-haspopup', true); + this.enabled_ = true; + + this.el_.setAttribute('aria-haspopup', 'true'); this.el_.setAttribute('role', 'menuitem'); this.on('keydown', this.handleSubmenuKeyPress); } @@ -50,7 +52,7 @@ class MenuButton extends ClickableComponent { * @private */ this.buttonPressed_ = false; - this.el_.setAttribute('aria-expanded', false); + this.el_.setAttribute('aria-expanded', 'false'); if (this.items && this.items.length === 0) { this.hide(); @@ -202,10 +204,12 @@ class MenuButton extends ClickableComponent { * @method pressButton */ pressButton() { - this.buttonPressed_ = true; - this.menu.lockShowing(); - this.el_.setAttribute('aria-expanded', true); - this.menu.focus(); // set the focus into the submenu + if (this.enabled_) { + this.buttonPressed_ = true; + this.menu.lockShowing(); + this.el_.setAttribute('aria-expanded', 'true'); + this.menu.focus(); // set the focus into the submenu + } } /** @@ -214,10 +218,41 @@ class MenuButton extends ClickableComponent { * @method unpressButton */ unpressButton() { + if (this.enabled_) { + this.buttonPressed_ = false; + this.menu.unlockShowing(); + this.el_.setAttribute('aria-expanded', 'false'); + this.el_.focus(); // Set focus back to this menu button + } + } + + /** + * Disable the menu button + * + * @return {Component} + * @method disable + */ + disable() { + // Unpress, but don't force focus on this button this.buttonPressed_ = false; this.menu.unlockShowing(); - this.el_.setAttribute('aria-expanded', false); - this.el_.focus(); // Set focus back to this menu button + this.el_.setAttribute('aria-expanded', 'false'); + + this.enabled_ = false; + + return super.disable(); + } + + /** + * Enable the menu button + * + * @return {Component} + * @method disable + */ + enable() { + this.enabled_ = true; + + return super.enable(); } } diff --git a/src/js/menu/menu-item.js b/src/js/menu/menu-item.js index 555abe0a03..0dd20e642d 100644 --- a/src/js/menu/menu-item.js +++ b/src/js/menu/menu-item.js @@ -66,13 +66,13 @@ class MenuItem extends ClickableComponent { if (this.selectable) { if (selected) { this.addClass('vjs-selected'); - this.el_.setAttribute('aria-checked',true); + this.el_.setAttribute('aria-checked','true'); // aria-checked isn't fully supported by browsers/screen readers, // so indicate selected state to screen reader in the control text. this.controlText(', selected'); } else { this.removeClass('vjs-selected'); - this.el_.setAttribute('aria-checked',false); + this.el_.setAttribute('aria-checked','false'); // Indicate un-selected state to screen reader // Note that a space clears out the selected state text this.controlText(' '); diff --git a/src/js/player.js b/src/js/player.js index ae72ca1136..c4214a9386 100644 --- a/src/js/player.js +++ b/src/js/player.js @@ -2473,13 +2473,13 @@ class Player extends Component { return this.techGet_('readyState'); } - /* - * Text tracks are tracks of timed text events. - * Captions - text displayed over the video for the hearing impaired - * Subtitles - text displayed over the video for those who don't understand language in the video - * Chapters - text displayed in a menu allowing the user to jump to particular points (chapters) in the video - * Descriptions (not supported yet) - audio descriptions that are read back to the user by a screen reading device - */ + /** + * Text tracks are tracks of timed text events. + * Captions - text displayed over the video for the hearing impaired + * Subtitles - text displayed over the video for those who don't understand language in the video + * Chapters - text displayed in a menu allowing the user to jump to particular points (chapters) in the video + * Descriptions - audio descriptions that are read back to the user by a screen reading device + */ /** * Get an array of associated text tracks. captions, subtitles, chapters, descriptions diff --git a/src/js/tracks/text-track-display.js b/src/js/tracks/text-track-display.js index e159b28357..bee096b6e6 100644 --- a/src/js/tracks/text-track-display.js +++ b/src/js/tracks/text-track-display.js @@ -83,6 +83,9 @@ class TextTrackDisplay extends Component { createEl() { return super.createEl('div', { className: 'vjs-text-track-display' + }, { + 'aria-live': 'assertive', + 'aria-atomic': 'true' }); } @@ -111,12 +114,30 @@ class TextTrackDisplay extends Component { return; } - for (let i=0; i < tracks.length; i++) { + // Track display prioritization model: if multiple tracks are 'showing', + // display the first 'subtitles' or 'captions' track which is 'showing', + // otherwise display the first 'descriptions' track which is 'showing' + + let descriptionsTrack = null; + let captionsSubtitlesTrack = null; + + let i = tracks.length; + while (i--) { let track = tracks[i]; if (track['mode'] === 'showing') { - this.updateForTrack(track); + if (track['kind'] === 'descriptions') { + descriptionsTrack = track; + } else { + captionsSubtitlesTrack = track; + } } } + + if (captionsSubtitlesTrack) { + this.updateForTrack(captionsSubtitlesTrack); + } else if (descriptionsTrack) { + this.updateForTrack(descriptionsTrack); + } } /** @@ -137,7 +158,7 @@ class TextTrackDisplay extends Component { cues.push(track['activeCues'][i]); } - window['WebVTT']['processCues'](window, track['activeCues'], this.el_); + window['WebVTT']['processCues'](window, cues, this.el_); let i = cues.length; while (i--) { diff --git a/test/api/api.js b/test/api/api.js index b0a12f1912..4bce4ca767 100644 --- a/test/api/api.js +++ b/test/api/api.js @@ -188,6 +188,7 @@ test('should export useful components to the public', function () { ok(videojs.getComponent('TextTrackButton'), 'TextTrackButton should be public'); ok(videojs.getComponent('CaptionsButton'), 'CaptionsButton should be public'); ok(videojs.getComponent('SubtitlesButton'), 'SubtitlesButton should be public'); + ok(videojs.getComponent('DescriptionsButton'), 'DescriptionsButton should be public'); ok(videojs.getComponent('ChaptersButton'), 'ChaptersButton should be public'); ok(videojs.getComponent('ChaptersTrackMenuItem'), 'ChaptersTrackMenuItem should be public'); diff --git a/test/unit/clickable-component.test.js b/test/unit/clickable-component.test.js index 1498b43a3a..b83b6c62e3 100644 --- a/test/unit/clickable-component.test.js +++ b/test/unit/clickable-component.test.js @@ -3,17 +3,38 @@ import TestHelpers from './test-helpers.js'; q.module('ClickableComponent'); -test('should create a div with role="button"', function(){ +q.test('should create a div with role="button"', function(){ expect(2); - var player, testClickableComponent, el; + let player = TestHelpers.makePlayer({}); - player = TestHelpers.makePlayer({ - }); - - testClickableComponent = new ClickableComponent(player); - el = testClickableComponent.createEl(); + let testClickableComponent = new ClickableComponent(player); + let el = testClickableComponent.createEl(); equal(el.nodeName.toLowerCase(), 'div', 'the name of the element is "div"'); equal(el.getAttribute('role').toLowerCase(), 'button', 'the role of the element is "button"'); + + testClickableComponent.dispose(); + player.dispose(); +}); + +q.test('should be enabled/disabled', function(){ + expect(3); + + let player = TestHelpers.makePlayer({}); + + let testClickableComponent = new ClickableComponent(player); + + equal(testClickableComponent.hasClass('vjs-disabled'), false, 'ClickableComponent defaults to enabled'); + + testClickableComponent.disable(); + + equal(testClickableComponent.hasClass('vjs-disabled'), true, 'ClickableComponent is disabled'); + + testClickableComponent.enable(); + + equal(testClickableComponent.hasClass('vjs-disabled'), false, 'ClickableComponent is enabled'); + + testClickableComponent.dispose(); + player.dispose(); }); diff --git a/test/unit/menu.test.js b/test/unit/menu.test.js index 5fbde6afcc..54838b92a8 100644 --- a/test/unit/menu.test.js +++ b/test/unit/menu.test.js @@ -1,21 +1,58 @@ import MenuButton from '../../src/js/menu/menu-button.js'; import TestHelpers from './test-helpers.js'; +import * as Events from '../../src/js/utils/events.js'; q.module('MenuButton'); -test('should place title list item into ul', function() { - var player, menuButton; +q.test('should place title list item into ul', function() { + let player = TestHelpers.makePlayer(); - player = TestHelpers.makePlayer(); - - menuButton = new MenuButton(player, { + let menuButton = new MenuButton(player, { 'title': 'testTitle' }); - var menuContentElement = menuButton.el().getElementsByTagName('UL')[0]; - var titleElement = menuContentElement.children[0]; + let menuContentElement = menuButton.el().getElementsByTagName('UL')[0]; + let titleElement = menuContentElement.children[0]; ok(titleElement.innerHTML === 'TestTitle', 'title element placed in ul'); player.dispose(); -}); \ No newline at end of file +}); + +q.test('clicking should display the menu', function() { + expect(6); + + let player = TestHelpers.makePlayer(); + + // Make sure there's some content in the menu, even if it's just a title! + let menuButton = new MenuButton(player, { + 'title': 'testTitle' + }); + let el = menuButton.el(); + + ok(menuButton.menu !== undefined, 'menu is created'); + + equal(menuButton.menu.hasClass('vjs-lock-showing'), false, 'menu defaults to hidden'); + + Events.trigger(el, 'click'); + + equal(menuButton.menu.hasClass('vjs-lock-showing'), true, 'clicking on the menu button shows the menu'); + + Events.trigger(el, 'click'); + + equal(menuButton.menu.hasClass('vjs-lock-showing'), false, 'clicking again on the menu button hides the menu'); + + menuButton.disable(); + + Events.trigger(el, 'click'); + + equal(menuButton.menu.hasClass('vjs-lock-showing'), false, 'disable() prevents clicking from showing the menu'); + + menuButton.enable(); + + Events.trigger(el, 'click'); + + equal(menuButton.menu.hasClass('vjs-lock-showing'), true, 'enable() allows clicking to show the menu'); + + player.dispose(); +}); diff --git a/test/unit/tracks/text-track-controls.test.js b/test/unit/tracks/text-track-controls.test.js index ca2fa9c4b1..27aa442521 100644 --- a/test/unit/tracks/text-track-controls.test.js +++ b/test/unit/tracks/text-track-controls.test.js @@ -110,6 +110,129 @@ test('menu should update with removeRemoteTextTrack', function() { player.dispose(); }); +let descriptionstrack = { + kind: 'descriptions', + label: 'desc' +}; + +test('descriptions should be displayed when text tracks list is not empty', function() { + let player = TestHelpers.makePlayer({ + tracks: [descriptionstrack] + }); + + this.clock.tick(1000); + + ok(!player.controlBar.descriptionsButton.hasClass('vjs-hidden'), 'descriptions control is displayed'); + equal(player.textTracks().length, 1, 'textTracks contains one item'); + + player.dispose(); +}); + +test('descriptions should be displayed when a text track is added to an empty track list', function() { + let player = TestHelpers.makePlayer(); + + player.addRemoteTextTrack(descriptionstrack); + + ok(!player.controlBar.descriptionsButton.hasClass('vjs-hidden'), 'control is displayed'); + equal(player.textTracks().length, 1, 'textTracks contains one item'); + + player.dispose(); +}); + +test('descriptions should not be displayed when text tracks list is empty', function() { + let player = TestHelpers.makePlayer(); + + ok(player.controlBar.descriptionsButton.hasClass('vjs-hidden'), 'control is not displayed'); + equal(player.textTracks().length, 0, 'textTracks is empty'); + + player.dispose(); +}); + +test('descriptions should not be displayed when last text track is removed', function() { + let player = TestHelpers.makePlayer({ + tracks: [descriptionstrack] + }); + + player.removeRemoteTextTrack(player.textTracks()[0]); + + ok(player.controlBar.descriptionsButton.hasClass('vjs-hidden'), 'control is not displayed'); + equal(player.textTracks().length, 0, 'textTracks is empty'); + + player.dispose(); +}); + +test('descriptions menu should contain "Off" and one track', function() { + let player = TestHelpers.makePlayer({ + tracks: [descriptionstrack] + }), + menuItems; + + this.clock.tick(1000); + + menuItems = player.controlBar.descriptionsButton.items; + + equal(menuItems.length, 2, 'descriptions menu contains two items'); + equal(menuItems[0].track.label, 'descriptions off', 'menu contains "descriptions off"'); + equal(menuItems[1].track.label, 'desc', 'menu contains "desc" track'); + + player.dispose(); +}); + +test('enabling a captions track should disable the descriptions menu button', function() { + expect(14); + + let player = TestHelpers.makePlayer({ + tracks: [track, descriptionstrack] + }); + + this.clock.tick(1000); + + ok(!player.controlBar.captionsButton.hasClass('vjs-hidden'), 'captions control is displayed'); + ok(!player.controlBar.descriptionsButton.hasClass('vjs-hidden'), 'descriptions control is displayed'); + equal(player.textTracks().length, 2, 'textTracks contains two items'); + + ok(!player.controlBar.captionsButton.hasClass('vjs-disabled'), 'captions control is NOT disabled'); + ok(!player.controlBar.descriptionsButton.hasClass('vjs-disabled'), 'descriptions control is NOT disabled'); + + for (let i = 0; i < player.textTracks().length; i++) { + if (player.textTracks()[i].kind === 'descriptions') { + player.textTracks()[i].mode = 'showing'; + ok(player.textTracks()[i].kind === 'descriptions' && player.textTracks()[i].mode === 'showing', 'descriptions mode set to showing'); + } + } + + this.clock.tick(1000); + + ok(!player.controlBar.captionsButton.hasClass('vjs-disabled'), 'captions control is NOT disabled'); + ok(!player.controlBar.descriptionsButton.hasClass('vjs-disabled'), 'descriptions control is NOT disabled'); + + for (let i = 0; i < player.textTracks().length; i++) { + if (player.textTracks()[i].kind === 'captions') { + player.textTracks()[i].mode = 'showing'; + ok(player.textTracks()[i].kind === 'captions' && player.textTracks()[i].mode === 'showing', 'captions mode set to showing'); + } + } + + this.clock.tick(1000); + + ok(!player.controlBar.captionsButton.hasClass('vjs-disabled'), 'captions control is NOT disabled'); + ok(player.controlBar.descriptionsButton.hasClass('vjs-disabled'), 'descriptions control IS disabled'); + + for (let i = 0; i < player.textTracks().length; i++) { + if (player.textTracks()[i].kind === 'captions') { + player.textTracks()[i].mode = 'disabled'; + ok(player.textTracks()[i].kind === 'captions' && player.textTracks()[i].mode === 'disabled', 'captions mode set to disabled'); + } + } + + this.clock.tick(1000); + + ok(!player.controlBar.captionsButton.hasClass('vjs-disabled'), 'captions control is NOT disabled'); + ok(!player.controlBar.descriptionsButton.hasClass('vjs-disabled'), 'descriptions control is NOT disabled'); + + player.dispose(); +}); + if (!browser.IS_IE8) { // This test doesn't work on IE8. // However, this test tests a specific with iOS7 where the TextTrackList doesn't report track mode changes. diff --git a/test/unit/tracks/tracks.test.js b/test/unit/tracks/tracks.test.js index 34937500a2..db1678bc59 100644 --- a/test/unit/tracks/tracks.test.js +++ b/test/unit/tracks/tracks.test.js @@ -1,4 +1,5 @@ import ChaptersButton from '../../../src/js/control-bar/text-track-controls/chapters-button.js'; +import DescriptionsButton from '../../../src/js/control-bar/text-track-controls/descriptions-button.js'; import SubtitlesButton from '../../../src/js/control-bar/text-track-controls/subtitles-button.js'; import CaptionsButton from '../../../src/js/control-bar/text-track-controls/captions-button.js'; @@ -135,9 +136,11 @@ test('update texttrack buttons on removetrack or addtrack', function() { let oldCaptionsUpdate; let oldSubsUpdate; let oldChaptersUpdate; + let oldDescriptionsUpdate; oldCaptionsUpdate = CaptionsButton.prototype.update; oldSubsUpdate = SubtitlesButton.prototype.update; + oldDescriptionsUpdate = DescriptionsButton.prototype.update; oldChaptersUpdate = ChaptersButton.prototype.update; CaptionsButton.prototype.update = function() { update++; @@ -147,6 +150,10 @@ test('update texttrack buttons on removetrack or addtrack', function() { update++; oldSubsUpdate.call(this); }; + DescriptionsButton.prototype.update = function() { + update++; + oldDescriptionsUpdate.call(this); + }; ChaptersButton.prototype.update = function() { update++; oldChaptersUpdate.call(this); @@ -186,19 +193,19 @@ test('update texttrack buttons on removetrack or addtrack', function() { player.player_ = player; - equal(update, 3, 'update was called on the three buttons during init'); + equal(update, 4, 'update was called on the four buttons during init'); for (i = 0; i < events.removetrack.length; i++) { events.removetrack[i](); } - equal(update, 6, 'update was called on the three buttons for remove track'); + equal(update, 8, 'update was called on the four buttons for remove track'); for (i = 0; i < events.addtrack.length; i++) { events.addtrack[i](); } - equal(update, 9, 'update was called on the three buttons for remove track'); + equal(update, 12, 'update was called on the four buttons for remove track'); Tech.prototype.textTracks = oldTextTracks; Tech.prototype.featuresNativeTextTracks = false;