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字幕的解析与同步显示算是讲完了。我觉得关键还是个思路,有了思路就有了代码。
SRT视频字幕的解析与同步原理相关推荐
- SRT视频字幕的解析与同步
转自:http://www.eoeandroid.com/thread-171556-1-1.html 在论坛搜索srt字幕的解析,没有资源,于是自己琢磨,有点结果,与大家分享. srt字幕文件的格式 ...
- 音视频同步原理解析;音频编码和解码原理
视频流中的DTS/PTS到底是什么? DTS(解码时间戳)和PTS(显示时间戳)分别是解码器进行解码和显示帧时相对于SCR(系统参考)的时间戳.SCR可以理解为解码器应该开始从磁盘读取数据时的时间. ...
- 转贴:网友【原创·教程】 SRT外挂字幕时间轴调整及合并中英文同步字幕制作方法
[原创·教程] SRT外挂字幕时间轴调整及合并中英文同步字幕制作方法 现时比较流行的一种外挂字幕之一就是SRT字幕了,视频电影在压制过程中如果加入字幕就会有损画质,所以就使用起外挂字幕,可隐藏可换多种 ...
- ffmpeg源码中ffplay音视频同步原理及实现
音视频指南 文章目录 音视频指南 前言 一.音视频同步简单介绍? 二.基本概念解释 1.为什么需要视频压缩 2.什么是I帧.p帧.b帧 3.什么是DTS,PTS 4.其他概念解释 三.常用同步策略 四 ...
- 转贴:网友【原创·教程】 SRT外挂字幕时间轴调整及合并中英文同步字幕制作方法...
[原创·教程]SRT外挂字幕时间轴调整及合并中英文同步字幕制作方法 现时比较流行的一种外挂字幕之一就是SRT字幕了,视频电影在压制过程中如果加入字幕就会有损画质,所以就使用起外挂字幕,可隐藏可换多种不 ...
- 转贴:网友【原创·教程】 SRT外挂字幕时间轴调整及合并中英文同步字幕制作方法 1
[原创·教程] SRT外挂字幕时间轴调整及合并中英文同步字幕制作方法 现时比较流行的一种外挂字幕之一就是SRT字幕了,视频电影在压制过程中如果加入字幕就会有损画质,所以就使用起外挂字幕,可隐藏可换多种 ...
- 同步播放的效果——iSubtitle for mac视频字幕制作可以做到!
同步播放的效果--iSubtitle for mac视频字幕制作可以做到!它不依赖于QuickTime或任何其他系统扩展或插件.支持批量导出和智能导入,iSubtitle for mac是一款可以将字 ...
- 音视频同步原理及实现
本文主要描述音视频同步原理,及常见的音视频同步方案,并以代码示例,展示如何以音频的播放时长为基准,将视频同步到音频上以实现视音频的同步播放.内容如下: 1.音视频同步简单介绍 2.DTS和PTS简介 ...
- 音视频同步原理[ffmpeg]
音视频同步原理[ffmpeg] output_example.c 中AV同步的代码如下(我的代码有些修改),这个实现相当简单,不过挺说明问题. 阅读前希望大家先了解一下时间戳的概念. /* compu ...
最新文章
- Yii中Action详解
- linux class device
- COCO 数据集的使用
- 实战|全程分析js到getshell
- common lisp 学习第三天 函数、注释
- 消消乐实现下坠_手把手教你如何实现iOS消消乐小游戏Demo
- 安装mongodb时为什么一直卡着不动
- ansible 基本操作(初试)
- 【Vue2.0】—Vue与Component的关系(十二)
- springboot 项目 测试环境在独立的tomcat部署
- Android 秒级编译 Freeline
- How Google Tests Software (出书,停止更新)
- arraylist长度_面经手册 第7篇ArrayList也这么多知识?一个指定位置插入就把谢飞机面晕了!...
- hdu5833 Zhu and 772002 (高斯消元的简单应用)
- KGB知识图谱,利用科技解决传统知识图谱问题
- VCL界面组件DevExpress VCL v22.1 - 发布全新的Shell组件
- MFC实现交通图导航系统
- linux终端关闭xmanager,xmanager之linux 解决方法
- 基于RFM模型对借贷App用户分层分析案例
- AV Foundationd 学习之(一)
热门文章
- 【软件开发】Java语言的简单介绍
- 仿照京东导航条html+css
- android paint 圆角 绘制_android 绘制椭圆 圆角矩形 详细解析
- 名校认证证书、免费课程……留学生不会告诉你的10个宝藏自学网站
- 中职网络安全操作系统渗透
- 学计算机的怎样分析TCGA数据库,开启数据挖掘之门:TCGA数据库入门必看!
- 我的项目: UConn summer academy BI制药 缺失值处理
- LintCode 1144.范围加法之二
- 在C ++中将二进制转换为十进制
- nativefier(一行代码将任意网页转化为桌面应用)