Одним из наиболее частых вопросов от пользователей Serenity для Google TV является возможность воспроизведения субтитров с фильмом. Plex действительно предоставляет информацию, если она там есть, но до Android 4.1 (она же Jelly Bean) не было встроенной поддержки субтитров для видеопроигрывателя. Даже тогда, кажется, есть проблемы с чтением потоков для субтитров. Устройства Google TV в настоящее время основаны на Android 3.2 (Honeycomb), у которой нет API для воспроизведения субтитров. Plex в этих случаях обычно транскодирует субтитры в видеопоток, однако Serenity не поддерживает транскодирование. Так что делать. Простой поворот к программному обеспечению с открытым исходным кодом для некоторой помощи.
На GitHub скрыт конвертер субтитров Дж. Дэвида Рекехо. Это был исследовательский проект PHD, и он позволяет конвертировать из одного формата субтитров в другой. Приятно то, что TimedTextObject содержит общий формат для субтитров. Как только он в этом формате, это вопрос навигации по дереву и проверки смещения времени, когда заголовок отображается и когда он должен исчезнуть.
Поскольку устройства Google TV не имеют встроенной поддержки отображения субтитров, как нам поступить? Serenity использует модифицированную версию MediaController и SurfaceView. Основное действие содержит следующий макет XML:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
<? xml version = '1.0' encoding = 'utf-8' ?> android:layout_width = 'fill_parent' android:layout_height = 'fill_parent' android:orientation = 'vertical' android:id = '@+id/video_playeback' android:background = '#000000' android:keepScreenOn = 'true' > < SurfaceView android:id = '@+id/surfaceView' android:layout_width = 'wrap_content' android:layout_height = 'wrap_content' android:layout_centerInParent = 'true' /> < TextView android:id = '@+id/txtSubtitles' android:layout_alignParentBottom = 'true' android:layout_height = 'wrap_content' android:layout_width = 'wrap_content' android:gravity = 'center' android:layout_centerHorizontal = 'true' android:visibility = 'invisible' style = '@android:style/TextAppearance.Large' /> </ RelativeLayout > |
Он содержит вид поверхности для видео, которое будет нарисовано, и TextView, который будет использоваться для отображения субтитров. Чтобы узнать, когда отображать субтитры во время воспроизведения, мы используем обработчик с небольшой задержкой, когда он должен выполняться. Когда он вызывается в первый раз, он запускается сразу. Каждое последующее выполнение задерживается на 100 миллисекунд.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
|
private Handler subtitleDisplayHandler = new Handler(); private Runnable subtitle = new Runnable() { public void run() { if (isMediaPlayerStateValid() && mediaPlayer.isPlaying()) { int currentPos = mediaPlayer.getCurrentPosition(); Collection<Caption> subtitles = srt.captions.values(); for (Caption caption : subtitles) { if (currentPos >= caption.start.getMilliseconds() && currentPos <= caption.end.getMilliseconds()) { onTimedText(caption); break ; } else if (currentPos > caption.end.getMilliseconds()) { onTimedText( null ); } } } subtitleDisplayHandler.postDelayed( this , SUBTITLE_DISPLAY_CHECK); }; }; |
PostDelayed повторно выполнит обработчик с запуском на указанное количество миллисекунд. OnTimedText — это то, что отвечает за отображение или скрытие субтитров во время воспроизведения.
1
2
3
4
5
6
7
8
9
|
public void onTimedText(Caption text) { TextView subtitles = (TextView) findViewById(R.id.txtSubtitles); if (text == null ) { subtitles.setVisibility(View.INVISIBLE); return ; } subtitles.setText(Html.fromHtml(text.content)); subtitles.setVisibility(View.VISIBLE); } |
Поскольку субтитры могут быть помечены HTML для указания курсива, полужирного шрифта или подчеркивания, мы используем метод Html.fromHtml, чтобы установить соответствующий текст и настроить видимость. Если текст был нулевым, вид скрыт. Весь процесс запускается асинхронной задачей, которая извлекает субтитры из Plex в виде потока.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
|
public class SubtitleAsyncTask extends AsyncTask<Void, Void, Void> { @Override protected Void doInBackground(Void... params) { if (subtitleURL != null ) { try { URL url = new URL(subtitleURL); InputStream stream = url.openStream(); FormatSRT formatSRT = new FormatSRT(); srt = formatSRT.parseFile(stream); subtitleDisplayHandler.post(subtitle); } catch (Exception e) { Log.e(getClass().getName(), e.getMessage(), e); } } // TODO Auto-generated method stub return null ; } } |
Это просто читает поток и анализирует отформатированные файлы субтитров SubRip (SRT) в TimedTextObject, а затем запускает обработчик.
Важно убедиться, что по завершении вашей деятельности вы удалите все обратные вызовы в обработчике. Поэтому обязательно сделайте следующее в вашем методе onFinish:
1
|
subtitleDisplayHandler.removeCallbacks(subtitle); |
Это должно работать независимо от версии Android. Он был протестирован на Android 3.2 в последней версии JellyBean. Если вам нужно манипулировать субтитрами, использовать их или преобразовывать их в другие форматы, вы можете попробовать проект subtitleConverter. Ожидайте увидеть эту поддержку с Serenity для Google TV v1.1.0.