`
lc_wangchao
  • 浏览: 34106 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

使用Java修改字幕文件

    博客分类:
  • Java
阅读更多
今天在下了一部电影,准备看时却发现网上的字幕都和电影不同步,整整差了一分钟。本来暴风倒是可以调节字幕的延迟,但最大只能延迟三十几秒,无奈之下只好手动改字幕……

字幕文件是.srt格式的,但考虑到其它文件格式的读取,先建立一个抽象的父类,以后不同类型文件的操作类都继承这个父类。

package movie;

public abstract class SubtitleDesigner {
	protected String src,des;
	public SubtitleDesigner(String src,String des){
		this.src = src;
		this.des = des;
	}
	
	public abstract boolean forward(long msecond);
	public abstract boolean delay(long msecond);
}


SubtitleDesigner实现了两个接口,forward和delay分别用来提前和延迟字幕。

下面就开始针对srt文件实现字幕的修改


子类除了实现父类的抽象方法外,还有几个私有方法:

private boolean editSubtitle(int ctl, long msecond)

主要的一个函数,实现字幕的延迟和提前操作。




private String[] getStartAndEndTime(String line)

从字幕文件中表示时间开始和结束的行中提取开始和结束时间,srt文件中像这样的行
00:00:00,229 --> 00:00:03,756
处理后会返回一个2维String,0和1的位置分别存储开始和结束的时间(在这里是00:00:00,229和00:00:03,756)




private int[] getTimes(String inTime)

从上面函数得到的字符串中获得时、分、秒、毫秒的整数值,存储在返回的int数组中





private long timesToMs(int times[])
private int[] msToTimes(long ms)

从上面函数得到的数组计算出毫秒数/从毫秒数得到时分秒毫秒的数组





private int[] reduceMs(int[] times, long ms)
private int[] addMs(int[] times, long ms)

提前/延迟一定时间,返回时分秒毫秒的整形数组。



整个类的具体实现是这样的:

package movie;

import java.io.*;
import java.util.regex.*;

public class SrtDesigner extends SubtitleDesigner {

	public static final int DELAY = 0;
	public static final int FORWARD = 1;

	public SrtDesigner(String src, String des) {
		super(src, des);
	}

	private long timesToMs(int times[]) {
		long ms;
		ms = (times[0] * 3600 + times[1] * 60 + times[2]) * 1000 + times[3];
		return ms;
	}

	private int[] msToTimes(long ms) {
		int[] times = new int[4];
		long tmp = ms;
		times[3] = (int) (tmp % 1000);
		tmp = tmp / 1000;
		times[2] = (int) (tmp % 60);
		tmp = tmp / 60;
		times[1] = (int) (tmp % 60);
		tmp = tmp / 60;
		times[0] = (int) (tmp);
		return times;
	}

	private int[] addMs(int[] times, long ms) {
		long tmp;
		int ret[];
		tmp = timesToMs(times);
		tmp += ms;
		ret = msToTimes(tmp);
		return ret;
	}

	private int[] reduceMs(int[] times, long ms) {
		long tmp;
		int ret[];
		tmp = timesToMs(times);
		tmp -= ms;
		if(tmp<0)
			return null;
		ret = msToTimes(tmp);
		return ret;
	}
	
	private String formatTime(int[] times){
		String ret;
		ret = String.format("%02d:%02d:%02d,%03d",times[0],times[1],times[2],times[3]);
		return ret;
	}
	
	private int[] getTimes(String inTime) {
		int[] times = new int[4];
		String tmp[] = inTime.split(",");
		times[3] = Integer.parseInt(tmp[1]);
		String time[] = tmp[0].split(":");
		times[0] = Integer.parseInt(time[0]);
		times[1] = Integer.parseInt(time[1]);
		times[2] = Integer.parseInt(time[2]);
		return times;
	}

	private String[] getStartAndEndTime(String line) {
		Pattern p = Pattern.compile("(\\d\\d:\\d\\d:\\d\\d,\\d\\d\\d)");
		Matcher m = p.matcher(line);
		String times[] = new String[2];
		times[0] = m.find() ? m.group() : null;
		times[1] = m.find() ? m.group() : null;
		//System.out.println("Start:" + times[0] + "End:" + times[1]);
		if (times[0] == null || times[1] == null)
			return null;
		return times;
	}

	private boolean editSubtitle(int ctl, long msecond) {
		File srcFile = new File(src);
		File desFile = new File(des);
		BufferedReader reader = null;
		BufferedWriter writer = null;
		boolean visibleFlag = true;//是否显示
		String line;
		try {
			reader = new BufferedReader(new FileReader(srcFile));
			writer = new BufferedWriter(new FileWriter(desFile));
			String regex = "\\d\\d:\\d\\d:\\d\\d,\\d\\d\\d --> \\d\\d:\\d\\d:\\d\\d,\\d\\d\\d";
			while ((line = reader.readLine()) != null) {
				if (Pattern.matches(regex, line)) {
					visibleFlag = true;
					String startAndEndTimes[];
					int startTimes[], endTimes[];
					if ((startAndEndTimes = getStartAndEndTime(line)) == null)
						return false;
					startTimes = getTimes(startAndEndTimes[0]);
					endTimes = getTimes(startAndEndTimes[1]);
					if(ctl == FORWARD){
						startTimes = reduceMs(startTimes, msecond);
						endTimes = reduceMs(endTimes, msecond);
						if(startTimes==null||endTimes==null){
							visibleFlag = false;
							continue;
						}
					}else{
						startTimes = addMs(startTimes, msecond);
						endTimes = addMs(endTimes, msecond);
					}
					line = formatTime(startTimes) + " --> " + formatTime(endTimes);
//					System.out.println(formatTime(startTimes));
//					System.out.println(formatTime(endTimes));
				}
				if(visibleFlag){
					writer.write(line + "\n");
					//System.out.println(line);
				}
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally{
			try {
				reader.close();
				writer.close();
			} catch (IOException e) {
				e.printStackTrace();
			}			
		}
		return true;
	}

	@Override
	public boolean delay(long msecond) {
		editSubtitle(DELAY, msecond);
		return false;
	}

	@Override
	public boolean forward(long msecond) {
		editSubtitle(FORWARD, msecond);
		return false;
	}

}



好了,在main函数中测试一下编好的类……


	public static void main(String args[]) {
		System.out.println("Dealing with file");
		SubtitleDesigner designer = new SrtDesigner("./src.srt", "./des.srt");
		designer.delay(59000);
		System.out.println("Done!!");
	}


源文件中有一段是这样的:
引用

1
00:00:00,229 --> 00:00:03,756
贝蒂,能到外面聊几句吗?

2
00:00:18,447 --> 00:00:21,780
- 什么事?可可
- 你姨妈打电话给我


生成的新文件里变为:
引用

1
00:00:59,229 --> 00:01:02,756
贝蒂,能到外面聊几句吗?

2
00:01:17,447 --> 00:01:20,780
- 什么事?可可
- 你姨妈打电话给我


正好延迟了59秒。
OK!终于可以看电影了(为了看这玩意花了我快一小时,容易么……)

以后有时间的话为这个程序再加一个图形界面吧,先把现有代码传上来。
0
1
分享到:
评论
1 楼 hiwon 2011-11-14  
非常好啊,用上了,谢谢博主。

相关推荐

    用java修改文件的编码

    用java修改文件的编码

    Java 读取、添加、删除修改json文件数据范例.rar

     读取nameID.txt文件中的NAMEID字段(key)对应值(value)并存储,读取NAMEID对应值,读取原始json文件并进行操作和输出,并创建一个包含原始json串的json对象,获取features数组的第i个json对象,读取properties...

    java创建TXT文件并进行读、写、修改操作

    java创建TXT文件并进行读、写、修改操作

    Java文件、文件夹权限修改的两种方法

    主要给大家介绍了关于Java文件、文件夹权限修改的两种方法,文中通过示例代码介绍的非常详细,对大家学习或者使用Java具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧

    java导出Word修改后缀名

    java导出文件, freemarker导出word需要ftl文件,java导出Word常见问题。2.TXT修改后缀名为.ftl

    java读TXT文件

    java读TXT文件,设置好路径和修改一下文件名就可以了

    文件复制、显示及修改java代码

    这是一个能够读取txt等文件的内容及修改的demo

    java把文本文件内容导入到数据库

    在生产企业中,会涉及到许多诸如把外部文件内容导入到数据库。本资源采用java程序开发,文本文件内容里的字段用“,”分开(如果是其他标识符,相应修改一下就行了),方便快捷。

    java spire.pdf 使用 对 pdf文件的相关操作

    自己写的 spire.pdf 简单...读取pdf将pdf转化为文字,最后由txt文件保存; 5.分割pdf ,包括按总页数,每页分割为一个 pdf文件,由于免费版原因,可以每9页生成一个pdf,或者根据 指定页数 (页) 根据指定页数 分割pdf

    文件同步修改工具

    SYNC程序同文件夹下建立一个data.txt文件 文件内容: 一行为一组需要同步文件的文件夹,两个地址用“,”逗号隔开, 程序是用java编写,请安装Java,我使用1.7以上jre,其他你们可以自己测试 程序目前最多同步两组...

    java文件注释清除工具

    1.仅支持删除java文件和txt文件;(如果想支持其他格式的文件,请用"."+格式后缀名替换clear_annot类的103行".txt"); 2.仅支持删除以注释开头的行该行前部的注释;(主要是为了删除jd-gui.exe反编译的文件前部的烦人...

    用java对文件进行操作

    .java文件,main中有测试用的代码,粘到src下可直接运行使用。 这个版本中目前有的方法为: 1.创建txt文件的方法。 2.过滤文件的方法。 3.修改文件名的方法。 4.获取文件大小,如果是文件夹则统计有多少个文件的方法...

    Java FTP 指定下载文件和上传文件到指定的服务器目录

    已经测试 完全没问题 大可以满足你的简单需求 修改液很容易 里面有详细的注释说明

    Java 版本的 OFD文件转换助手

    项目未使用maven架构,整理了ofd转换所需的完整jar包,...另附调用源码,可支持读取ofd文件以及 ofd文件的base64编码转换(主要用于从数据库中加载到的数据),代码结构简单明了,可根据所需业务自行修改或调整代码。

    java源码包---java 源码 大量 实例

     Java访问权限控制,为Java操作文件、写入文件分配合适的权限,定义写到文件的信息、定义文件,输出到c:/hello.txt、写信息到文件、关闭输出流。 Java绘制图片火焰效果 1个目标文件 摘要:Java源码,图形操作,火焰...

    用于修改jar文件包路径

    这里我们以 gson.jar 为例,在 gson.jar 包目录下新建一个文本文件,名字随意,例如 rule.txt,写入下面的内容。 rule com.google.gson.** com.google.mygson.@1 上面写的就是修改规则,我们将包名中的 gson 修改为...

    JAVA上百实例源码以及开源项目

     Java访问权限控制,为Java操作文件、写入文件分配合适的权限,定义写到文件的信息、定义文件,输出到c:/hello.txt、写信息到文件、关闭输出流。 Java绘制图片火焰效果 1个目标文件 摘要:Java源码,图形操作,火焰...

    使用Java的网络编程实现一个简单的文件传输系统.txt

    主要使用了Java的网络编程和文件操作技术。 首先定义了一个FileTransferServer类,在main方法中创建了一个ServerSocket对象,监听指定端口(本例中为8080)。然后进入一个无限循环,等待客户端的连接请求。当有...

    Java实现批量修改txt文件名称的方法示例

    主要介绍了Java实现批量修改txt文件名称的方法,结合实例形式分析了Java针对目录文件遍历及文件读写、属性操作等相关实现技巧,需要的朋友可以参考下

Global site tag (gtag.js) - Google Analytics