SRT视频字幕的解析与同步

转自:http://www.eoeandroid.com/thread-171556-1-1.html


在论坛搜索srt字幕的解析,没有资源,于是自己琢磨,有点结果,与大家分享。


srt字幕文件的格式是:
1
00:00:02,580 --> 00:00:05,980
This is from Gagarin.

2
00:00:11,260 --> 00:00:15,760
<b><u><font color='RED'>出卖我的爱.</font></u></b>
<b><u><font color='RED'>       离开就离开.</font></u></b>
<b><u><font color='RED'>       分手就分手.</font></u></b>
<b><u><font color='RED'>没啥了不起.</font></u></b>

3
00:00:18,660 --> 00:00:22,660
初次发帖,欢迎分享.

4
00:00:23,860 --> 00:00:30,860
Trust is like a piece of paper. When it creases, it cannot recover even it is smoothed.
信任就像一张纸,皱了,即使抚平,也恢复不了原样了。

即:
数字
时间 --> 时间
字幕内容(可以多行)
空行
数字
时间 --> 时间
字幕内容(可以多行)
空行
.
.
.
这里为了说明方便,把
数字
时间 --> 时间
字幕内容(可以多行)
空行
叫做字幕元素。

思路应该是比较清晰的,先解析字幕后同步显示字幕。


1.解析字幕
字幕在解析的时候,就是解析出每一个字幕元素。关键是字幕元素的时间和内容,时间可以解析出开始时间和结束时间,内容可能一行,可能多行,有的还有格式。这里我们可以先声明一个SRT的Bean来存放解析出来的字幕元素。

package wjj.player.entity;
 
public class SRT {
private int beginTime;
private int endTime;
private String srtBody;
 
public int getBeginTime() {
return beginTime;
}
 
public void setBeginTime(int beginTime) {
this.beginTime = beginTime;
}
 
public int getEndTime() {
return endTime;
}
 
public void setEndTime(int endTime) {
this.endTime = endTime;
}
 
public String getSrtBody() {
return srtBody;
}
 
public void setSrtBody(String srtBody) {
this.srtBody = srtBody;
}
 
@Override
public String toString() {
return "" + beginTime + ":" + endTime + ":" + srtBody;
}
}

然后就可以把字幕解析的结果放在这个SRT的对象中,由于字幕文件中有多个字幕元素,我们可以把它放在一个Map中存放。这里选用TreeMap。声明一个全局变量 TreeMap<Integer, SRT> srt_map =null;于是就可以把整个字幕文件解析到这个TreeMap中。


/**
* 解析SRT字幕文件
* 
* @param srtPath
* 字幕路径
*/
private void parseSrt(String srtPath) {
FileInputStream inputStream = null;
try {
inputStream = new FileInputStream(srtPath);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return;// 有异常,就没必要继续下去了
}
BufferedReader br = new BufferedReader(new InputStreamReader(
inputStream));
String line = null;
srt_map = new TreeMap<Integer, SRT>();
StringBuffer sb = new StringBuffer();
int key = 0;
try {
while ((line = br.readLine()) != null) {
if (!line.equals("")) {
sb.append(line).append("@");
continue;
}
 
String[] parseStrs = sb.toString().split("@");
// 该if为了适应一开始就有空行以及其他不符格式的空行情况
if (parseStrs.length < 3) {
<i>sb.delete(0, sb.length());// 清空,否则影响下一个字幕元素的解析</i>
continue;
}
 
SRT srt = new SRT();
// 解析开始和结束时间
String timeTotime = parseStrs[1];
int begin_hour = Integer.parseInt(timeTotime.substring(0, 2));
int begin_mintue = Integer.parseInt(timeTotime.substring(3, 5));
int begin_scend = Integer.parseInt(timeTotime.substring(6, 8));
int begin_milli = Integer.parseInt(timeTotime.substring(9, 12));
int beginTime = (begin_hour * 3600 + begin_mintue * 60 + begin_scend)
* 1000 + begin_milli;
int end_hour = Integer.parseInt(timeTotime.substring(17, 19));
int end_mintue = Integer.parseInt(timeTotime.substring(20, 22));
int end_scend = Integer.parseInt(timeTotime.substring(23, 25));
int end_milli = Integer.parseInt(timeTotime.substring(26, 29));
int endTime = (end_hour * 3600 + end_mintue * 60 + end_scend)
* 1000 + end_milli;
 
// System.out.println("开始:" + begin_hour + ":" + begin_mintue +
// ":"
// + begin_scend + ":" + begin_milli + "=" + beginTime
// + "ms");
// System.out.println("结束:" + end_hour + ":" + end_mintue + ":"
// + end_scend + ":" + end_milli + "=" + endTime + "ms");
// 解析字幕文字
String srtBody = "";
// 可能1句字幕,也可能2句及以上。
for (int i = 2; i < parseStrs.length; i++) {
srtBody += parseStrs</strong><i><strong> + "\n";
}
// 删除最后一个"\n"
srtBody = srtBody.substring(0, srtBody.length() - 1);
// 设置SRT
srt.setBeginTime(beginTime);
srt.setEndTime(endTime);
srt.setSrtBody(new String(srtBody.getBytes(), "UTF-8"));
// 插入队列
srt_map.put(key, srt);
key++;
sb.delete(0, sb.length());// 清空,否则影响下一个字幕元素的解析
}
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}

2.同步显示
解析完成后,接下来就是显示的问题了。由于SRT字幕元素中有了开始时间,结束时间,而播放器也可以通过getCurrentPosition()获得当前播放的时间,同步显示的原理就是先获取当前播放时间,然后与SRT字幕元素中的开始时间和结束时间比较,在此范围内的就可以显示SRT字幕元素中的字幕内容。比较是通过一个while循环遍历完成。


private void showSRT() {
TextView tvSrt = (TextView) srtView.findViewById(R.id.srt);//项目中显示字幕的控件
int currentPosition = vv.getCurrentPosition();//vv是VideoView播放器
Iterator<Integer> keys = srt_map.keySet().iterator();
//通过while循环遍历比较
while (keys.hasNext()) {
Integer key = keys.next();
SRT srtbean = srt_map.get(key);
if (currentPosition > srtbean.getBeginTime()
&& currentPosition < srtbean.getEndTime()) {
//Html.fromHtml可以解析出字幕内容的格式
Spanned srtBodyHtml = Html.fromHtml(srtbean
.getSrtBody());
tvsrt.setText(srtBodyHtml);
break;//找到后就没必要继续遍历下去,节约资源
}
}
}

到此SRT字幕的解析与同步显示算是讲完了。我觉得关键还是个思路,有了思路就有了代码。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值