├── .classpath
├── .gitignore
├── .project
├── AndroidManifest.xml
├── README.md
├── gen
└── com
│ └── example
│ └── media
│ └── timedtexttest
│ ├── BuildConfig.java
│ └── R.java
├── ic_launcher-web.png
├── libs
└── android-support-v4.jar
├── proguard-project.txt
├── project.properties
├── res
├── drawable-hdpi
│ └── ic_launcher.png
├── drawable-ldpi
│ └── ic_launcher.png
├── drawable-mdpi
│ └── ic_launcher.png
├── drawable-xhdpi
│ └── ic_launcher.png
├── layout
│ └── activity_main.xml
├── menu
│ └── activity_main.xml
├── raw
│ ├── sub.srt
│ └── video.mp4
├── values-v11
│ └── styles.xml
├── values-v14
│ └── styles.xml
└── values
│ ├── strings.xml
│ └── styles.xml
└── src
└── com
└── example
└── media
└── timedtexttest
└── MainActivity.java
/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /bin
2 |
--------------------------------------------------------------------------------
/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | TimedTextTest
4 |
5 |
6 |
7 |
8 |
9 | com.android.ide.eclipse.adt.ResourceManagerBuilder
10 |
11 |
12 |
13 |
14 | com.android.ide.eclipse.adt.PreCompilerBuilder
15 |
16 |
17 |
18 |
19 | org.eclipse.jdt.core.javabuilder
20 |
21 |
22 |
23 |
24 | com.android.ide.eclipse.adt.ApkBuilder
25 |
26 |
27 |
28 |
29 |
30 | com.android.ide.eclipse.adt.AndroidNature
31 | org.eclipse.jdt.core.javanature
32 |
33 |
34 |
--------------------------------------------------------------------------------
/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
10 |
11 |
16 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | TimedTextTest
2 | =============
3 |
4 | An example project of using TimedText in android 4.0+ to add subtitles to a video.
5 |
6 |
7 | It is related to the below StackOverflow question:
8 |
9 | http://stackoverflow.com/questions/13422673/looking-for-a-working-example-of-addtimedtextsource-for-adding-subtitle-to-a-vid/14929323?noredirect=1#comment22672683_14929323
10 |
--------------------------------------------------------------------------------
/gen/com/example/media/timedtexttest/BuildConfig.java:
--------------------------------------------------------------------------------
1 | /** Automatically generated file. DO NOT MODIFY */
2 | package com.example.media.timedtexttest;
3 |
4 | public final class BuildConfig {
5 | public final static boolean DEBUG = true;
6 | }
--------------------------------------------------------------------------------
/gen/com/example/media/timedtexttest/R.java:
--------------------------------------------------------------------------------
1 | /* AUTO-GENERATED FILE. DO NOT MODIFY.
2 | *
3 | * This class was automatically generated by the
4 | * aapt tool from the resource data it found. It
5 | * should not be modified by hand.
6 | */
7 |
8 | package com.example.media.timedtexttest;
9 |
10 | public final class R {
11 | public static final class attr {
12 | }
13 | public static final class drawable {
14 | public static final int ic_launcher=0x7f020000;
15 | }
16 | public static final class id {
17 | public static final int menu_settings=0x7f080001;
18 | public static final int txtDisplay=0x7f080000;
19 | }
20 | public static final class layout {
21 | public static final int activity_main=0x7f030000;
22 | }
23 | public static final class menu {
24 | public static final int activity_main=0x7f070000;
25 | }
26 | public static final class raw {
27 | public static final int sub=0x7f040000;
28 | public static final int video=0x7f040001;
29 | }
30 | public static final class string {
31 | public static final int app_name=0x7f050000;
32 | public static final int hello_world=0x7f050001;
33 | public static final int menu_settings=0x7f050002;
34 | }
35 | public static final class style {
36 | /**
37 | Base application theme, dependent on API level. This theme is replaced
38 | by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
39 |
40 |
41 | Theme customizations available in newer API levels can go in
42 | res/values-vXX/styles.xml, while customizations related to
43 | backward-compatibility can go here.
44 |
45 |
46 | Base application theme for API 11+. This theme completely replaces
47 | AppBaseTheme from res/values/styles.xml on API 11+ devices.
48 |
49 | API 11 theme customizations can go here.
50 |
51 | Base application theme for API 14+. This theme completely replaces
52 | AppBaseTheme from BOTH res/values/styles.xml and
53 | res/values-v11/styles.xml on API 14+ devices.
54 |
55 | API 14 theme customizations can go here.
56 | */
57 | public static final int AppBaseTheme=0x7f060000;
58 | /** Application theme.
59 | All customizations that are NOT specific to a particular API-level can go here.
60 | */
61 | public static final int AppTheme=0x7f060001;
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/ic_launcher-web.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iTech-Developer/TimedTextTest/79ea1006d572a244d9ea163291ac3a4e36ddc677/ic_launcher-web.png
--------------------------------------------------------------------------------
/libs/android-support-v4.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iTech-Developer/TimedTextTest/79ea1006d572a244d9ea163291ac3a4e36ddc677/libs/android-support-v4.jar
--------------------------------------------------------------------------------
/proguard-project.txt:
--------------------------------------------------------------------------------
1 | # To enable ProGuard in your project, edit project.properties
2 | # to define the proguard.config property as described in that file.
3 | #
4 | # Add project specific ProGuard rules here.
5 | # By default, the flags in this file are appended to flags specified
6 | # in ${sdk.dir}/tools/proguard/proguard-android.txt
7 | # You can edit the include path and order by changing the ProGuard
8 | # include property in project.properties.
9 | #
10 | # For more details, see
11 | # http://developer.android.com/guide/developing/tools/proguard.html
12 |
13 | # Add any project specific keep options here:
14 |
15 | # If your project uses WebView with JS, uncomment the following
16 | # and specify the fully qualified class name to the JavaScript interface
17 | # class:
18 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
19 | # public *;
20 | #}
21 |
--------------------------------------------------------------------------------
/project.properties:
--------------------------------------------------------------------------------
1 | # This file is automatically generated by Android Tools.
2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED!
3 | #
4 | # This file must be checked in Version Control Systems.
5 | #
6 | # To customize properties used by the Ant build system edit
7 | # "ant.properties", and override values to adapt the script to your
8 | # project structure.
9 | #
10 | # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
11 | #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
12 |
13 | # Project target.
14 | target=android-16
15 |
--------------------------------------------------------------------------------
/res/drawable-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iTech-Developer/TimedTextTest/79ea1006d572a244d9ea163291ac3a4e36ddc677/res/drawable-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/res/drawable-ldpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iTech-Developer/TimedTextTest/79ea1006d572a244d9ea163291ac3a4e36ddc677/res/drawable-ldpi/ic_launcher.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iTech-Developer/TimedTextTest/79ea1006d572a244d9ea163291ac3a4e36ddc677/res/drawable-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/res/drawable-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iTech-Developer/TimedTextTest/79ea1006d572a244d9ea163291ac3a4e36ddc677/res/drawable-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
14 |
15 |
--------------------------------------------------------------------------------
/res/menu/activity_main.xml:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/res/raw/sub.srt:
--------------------------------------------------------------------------------
1 | 1
2 | 00:00:00,220 --> 00:00:01,215
3 | First Text Example
4 |
5 | 2
6 | 00:00:03,148 --> 00:00:05,053
7 | Second Text Example
8 |
9 | 3
10 | 00:00:08,004 --> 00:00:09,884
11 | Third Text Example
12 |
13 | 4
14 | 00:00:11,300 --> 00:00:12,900
15 | Fourth Text Example
16 |
17 | 5
18 | 00:00:15,500 --> 00:00:16,700
19 | Fifth Text Example
20 |
21 | 6
22 | 00:00:18,434 --> 00:00:20,434
23 | Sixth Text Example
24 |
25 | 7
26 | 00:00:22,600 --> 00:00:23,700
27 | Last Text Example
28 |
--------------------------------------------------------------------------------
/res/raw/video.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iTech-Developer/TimedTextTest/79ea1006d572a244d9ea163291ac3a4e36ddc677/res/raw/video.mp4
--------------------------------------------------------------------------------
/res/values-v11/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/res/values-v14/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
11 |
12 |
--------------------------------------------------------------------------------
/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | TimedTextTest
5 | Hello world!
6 | Settings
7 |
8 |
--------------------------------------------------------------------------------
/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
14 |
15 |
16 |
19 |
20 |
--------------------------------------------------------------------------------
/src/com/example/media/timedtexttest/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.example.media.timedtexttest;
2 |
3 | import java.io.Closeable;
4 | import java.io.File;
5 | import java.io.FileOutputStream;
6 | import java.io.IOException;
7 | import java.io.InputStream;
8 | import java.io.OutputStream;
9 | import java.util.Locale;
10 |
11 | import android.app.Activity;
12 | import android.media.MediaPlayer;
13 | import android.media.MediaPlayer.OnTimedTextListener;
14 | import android.media.MediaPlayer.TrackInfo;
15 | import android.media.TimedText;
16 | import android.os.Bundle;
17 | import android.os.Handler;
18 | import android.util.Log;
19 | import android.widget.TextView;
20 |
21 | public class MainActivity extends Activity implements OnTimedTextListener {
22 | private static final String TAG = "TimedTextTest";
23 | private TextView txtDisplay;
24 | private static Handler handler = new Handler();
25 |
26 | @Override
27 | protected void onCreate(Bundle savedInstanceState) {
28 | super.onCreate(savedInstanceState);
29 | setContentView(R.layout.activity_main);
30 | txtDisplay = (TextView) findViewById(R.id.txtDisplay);
31 | MediaPlayer player = MediaPlayer.create(this, R.raw.video);
32 | try {
33 | player.addTimedTextSource(getSubtitleFile(R.raw.sub),
34 | MediaPlayer.MEDIA_MIMETYPE_TEXT_SUBRIP);
35 | int textTrackIndex = findTrackIndexFor(
36 | TrackInfo.MEDIA_TRACK_TYPE_TIMEDTEXT, player.getTrackInfo());
37 | if (textTrackIndex >= 0) {
38 | player.selectTrack(textTrackIndex);
39 | } else {
40 | Log.w(TAG, "Cannot find text track!");
41 | }
42 | player.setOnTimedTextListener(this);
43 | player.start();
44 | } catch (Exception e) {
45 | e.printStackTrace();
46 | }
47 | }
48 |
49 | private int findTrackIndexFor(int mediaTrackType, TrackInfo[] trackInfo) {
50 | int index = -1;
51 | for (int i = 0; i < trackInfo.length; i++) {
52 | if (trackInfo[i].getTrackType() == mediaTrackType) {
53 | return i;
54 | }
55 | }
56 | return index;
57 | }
58 |
59 | private String getSubtitleFile(int resId) {
60 | String fileName = getResources().getResourceEntryName(resId);
61 | File subtitleFile = getFileStreamPath(fileName);
62 | if (subtitleFile.exists()) {
63 | Log.d(TAG, "Subtitle already exists");
64 | return subtitleFile.getAbsolutePath();
65 | }
66 | Log.d(TAG, "Subtitle does not exists, copy it from res/raw");
67 |
68 | // Copy the file from the res/raw folder to your app folder on the
69 | // device
70 | InputStream inputStream = null;
71 | OutputStream outputStream = null;
72 | try {
73 | inputStream = getResources().openRawResource(resId);
74 | outputStream = new FileOutputStream(subtitleFile, false);
75 | copyFile(inputStream, outputStream);
76 | return subtitleFile.getAbsolutePath();
77 | } catch (Exception e) {
78 | e.printStackTrace();
79 | } finally {
80 | closeStreams(inputStream, outputStream);
81 | }
82 | return "";
83 | }
84 |
85 | private void copyFile(InputStream inputStream, OutputStream outputStream)
86 | throws IOException {
87 | final int BUFFER_SIZE = 1024;
88 | byte[] buffer = new byte[BUFFER_SIZE];
89 | int length = -1;
90 | while ((length = inputStream.read(buffer)) != -1) {
91 | outputStream.write(buffer, 0, length);
92 | }
93 | }
94 |
95 | // A handy method I use to close all the streams
96 | private void closeStreams(Closeable... closeables) {
97 | if (closeables != null) {
98 | for (Closeable stream : closeables) {
99 | if (stream != null) {
100 | try {
101 | stream.close();
102 | } catch (IOException e) {
103 | e.printStackTrace();
104 | }
105 | }
106 | }
107 | }
108 | }
109 |
110 | @Override
111 | public void onTimedText(final MediaPlayer mp, final TimedText text) {
112 | if (text != null) {
113 | handler.post(new Runnable() {
114 | @Override
115 | public void run() {
116 | int seconds = mp.getCurrentPosition() / 1000;
117 |
118 | txtDisplay.setText("[" + secondsToDuration(seconds) + "] "
119 | + text.getText());
120 | }
121 | });
122 | }
123 | }
124 |
125 | // To display the seconds in the duration format 00:00:00
126 | public String secondsToDuration(int seconds) {
127 | return String.format("%02d:%02d:%02d", seconds / 3600,
128 | (seconds % 3600) / 60, (seconds % 60), Locale.US);
129 | }
130 | }
131 |
--------------------------------------------------------------------------------