самопальная прожка для ретаймирования сабов
Решил вот посмотреть "Порко Россо", а там то ли сабы кривые, то ли фильм кривой - расходятся в тайминге, в общем. Причем прогрессирующая задержка, так что простым retime тут не обойтись. Для решения проблемы написал свою прожку на жаве.
в начале фильма надо на 2 сек. опережение сабов выставить
00:02:00 -2000 msec
в конце фильма уже 210 сек. задержки
01:28:00 +210000 msec
Т.е. налицо прогрессирующиее отставание титров в файле от фильма.
При этом 65 минут сабов соответствуют приблизительно 68 минутам фильма.
Например, реплика с сабах
25
00:02:46,823 --> 00:02:49,121
Пора бы уже перебрать...
точно соответствует фильму, причем предыдущие отстают, а последующие опережают.
А вот для того, чтобы реплика
1138
01:24:26,754 --> 01:24:28,952
Сюда летят Итальянские ВВС.
соответствовала фильму, нужно ввести задержку 210000 мсек,
тогда она будет начинаться в 01:27:57
Т.е., в результате имеем
саб 00:02:46,823, задержка 0, фильм 00:02:46
саб 01:24:26,754, задержка 210000, фильм 01:27:57
Значит, в промежутке между этими сабами задержка равномерно увеличивается
от 0 до 210 сек. Т.е., если брать в секундах, то выходит следующее:
00:02:46 = 0*3600 + 2*60 + 46 = 166 сек, задержка 0 сек.
01:24:26 = 1*3600 + 24*60 + 26 = 5066 сек, задержка 210 сек.
Значит, в течении
5066 - 166 = 4900 сек.
задержка равномерно (предположительно) возрастает
Скорость возрастания задержки в таком случае будет
delspeed = 210/4900 = 0,04285714285
Именно эту величину нужно прибавлять к задержке каждую секунду.
Значит, новое время в секундах будет выглядеть так:
newsec = oldsec + oldsec*delspeed;
А если все это воплотить в строчках кода, то будет так:
import java.io.*;
import java.util.*;
public class Subtitler {
/**
* @param args
*/
public static void main(String[] args) throws IOException, FileNotFoundException, UnsupportedEncodingException
{
// TODO Auto-generated method stub
String infile = "E:\\Anime\\Porco Rosso\\cor.movie.porco.rosso.[6DF3E41F].srt";
String outfile = "E:\\Anime\\Porco Rosso\\converted.srt";
double addPerSec = (double)210/4900;
final int constDelay = 6800;
FileInputStream fin = new FileInputStream(infile);
DataInputStream din = new DataInputStream(fin);
FileOutputStream fout = new FileOutputStream(outfile);
DataOutputStream dout = new DataOutputStream(fout);
String str;
Date firstSubBeginDate = null;
MyDate curSubBeginDate = null, curSubEndDate = null;
SrtTitleReader titlereader = new SrtTitleReader();
SrtTitleWriter titlewriter = new SrtTitleWriter();
int titleNo = 0;
while((str = din.readLine()) != null) {
if(str.indexOf("-->") >= 0) {
titleNo++;
titlereader.setTitleStr(str);
if(titleNo == 1)
firstSubBeginDate = titlereader.getTitleBeginDate();
curSubBeginDate = titlereader.getTitleBeginDate();
curSubEndDate = titlereader.getTitleEndDate();
long deltamsec = curSubBeginDate.getTime() - firstSubBeginDate.getTime();
double curDelay = (addPerSec*(double)deltamsec);
curSubBeginDate.setTime(curSubBeginDate.getTime() + (long)curDelay - constDelay);
curSubEndDate.setTime(curSubEndDate.getTime() + (long)curDelay - constDelay);
titlewriter.setTitleBeginDate(curSubBeginDate);
titlewriter.setTitleEndDate(curSubEndDate);
//System.out.println("old: \"" + str + "\", new: \"" + titlewriter.getTitleStr() + "\", " + (long)curDelay);
str = titlewriter.getTitleStr();
}
dout.writeBytes(str);
dout.writeBytes("\n");
};
System.out.println("Converted " + titleNo + " titles ");
}
}
class MyDate extends Date {
public MyDate() {
super();
}
public void setMilliseconds(int msec) {
if(msec <>= 1000) return;
setTime((getTime()/1000)*1000);
setTime(getTime() + msec);
}
public long getMilliseconds() {
long sec = getTime()/1000;
long msec = getTime() - sec*1000;
return msec;
}
}
class SrtTitleReader {
private String titleSrtFmt;
public SrtTitleReader() {};
public void setTitleStr(String title) {
titleSrtFmt = title.trim();
}
private MyDate getTitleDate(String title) {
int hour = Integer.valueOf(title.substring(0, 2));
int min = Integer.valueOf(title.substring(3, 5));
int sec = Integer.valueOf(title.substring(6, 8));
int msec = Integer.valueOf(title.substring(9, 12));
MyDate titledate = new MyDate();
titledate.setHours(hour);
titledate.setMinutes(min);
titledate.setSeconds(sec);
titledate.setMilliseconds(msec);
return titledate;
}
public MyDate getTitleBeginDate() {
return getTitleDate(titleSrtFmt.substring(0, 12));
}
public MyDate getTitleEndDate() {
String endtitle = titleSrtFmt.substring(12);
endtitle = endtitle.replaceAll("-->", "").trim();
return getTitleDate(endtitle);
}
}
class SrtTitleWriter {
public SrtTitleWriter() {};
private MyDate titleBeginDate = null;
private MyDate titleEndDate = null;
public void setTitleBeginDate(MyDate begindate) {
titleBeginDate = begindate;
}
public void setTitleEndDate(MyDate begindate) {
titleEndDate = begindate;
}
public String getTitleStr() {
String begintitl = String.format("%1$02d:%2$02d:%3$02d,%4$03d",
titleBeginDate.getHours(), titleBeginDate.getMinutes(),
titleBeginDate.getSeconds(), titleBeginDate.getMilliseconds());
String endtitl = String.format("%1$02d:%2$02d:%3$02d,%4$03d",
titleEndDate.getHours(), titleEndDate.getMinutes(),
titleEndDate.getSeconds(), titleEndDate.getMilliseconds());
return (begintitl + " --> " + endtitl);
}
}
в начале фильма надо на 2 сек. опережение сабов выставить
00:02:00 -2000 msec
в конце фильма уже 210 сек. задержки
01:28:00 +210000 msec
Т.е. налицо прогрессирующиее отставание титров в файле от фильма.
При этом 65 минут сабов соответствуют приблизительно 68 минутам фильма.
Например, реплика с сабах
25
00:02:46,823 --> 00:02:49,121
Пора бы уже перебрать...
точно соответствует фильму, причем предыдущие отстают, а последующие опережают.
А вот для того, чтобы реплика
1138
01:24:26,754 --> 01:24:28,952
Сюда летят Итальянские ВВС.
соответствовала фильму, нужно ввести задержку 210000 мсек,
тогда она будет начинаться в 01:27:57
Т.е., в результате имеем
саб 00:02:46,823, задержка 0, фильм 00:02:46
саб 01:24:26,754, задержка 210000, фильм 01:27:57
Значит, в промежутке между этими сабами задержка равномерно увеличивается
от 0 до 210 сек. Т.е., если брать в секундах, то выходит следующее:
00:02:46 = 0*3600 + 2*60 + 46 = 166 сек, задержка 0 сек.
01:24:26 = 1*3600 + 24*60 + 26 = 5066 сек, задержка 210 сек.
Значит, в течении
5066 - 166 = 4900 сек.
задержка равномерно (предположительно) возрастает
Скорость возрастания задержки в таком случае будет
delspeed = 210/4900 = 0,04285714285
Именно эту величину нужно прибавлять к задержке каждую секунду.
Значит, новое время в секундах будет выглядеть так:
newsec = oldsec + oldsec*delspeed;
А если все это воплотить в строчках кода, то будет так:
import java.io.*;
import java.util.*;
public class Subtitler {
/**
* @param args
*/
public static void main(String[] args) throws IOException, FileNotFoundException, UnsupportedEncodingException
{
// TODO Auto-generated method stub
String infile = "E:\\Anime\\Porco Rosso\\cor.movie.porco.rosso.[6DF3E41F].srt";
String outfile = "E:\\Anime\\Porco Rosso\\converted.srt";
double addPerSec = (double)210/4900;
final int constDelay = 6800;
FileInputStream fin = new FileInputStream(infile);
DataInputStream din = new DataInputStream(fin);
FileOutputStream fout = new FileOutputStream(outfile);
DataOutputStream dout = new DataOutputStream(fout);
String str;
Date firstSubBeginDate = null;
MyDate curSubBeginDate = null, curSubEndDate = null;
SrtTitleReader titlereader = new SrtTitleReader();
SrtTitleWriter titlewriter = new SrtTitleWriter();
int titleNo = 0;
while((str = din.readLine()) != null) {
if(str.indexOf("-->") >= 0) {
titleNo++;
titlereader.setTitleStr(str);
if(titleNo == 1)
firstSubBeginDate = titlereader.getTitleBeginDate();
curSubBeginDate = titlereader.getTitleBeginDate();
curSubEndDate = titlereader.getTitleEndDate();
long deltamsec = curSubBeginDate.getTime() - firstSubBeginDate.getTime();
double curDelay = (addPerSec*(double)deltamsec);
curSubBeginDate.setTime(curSubBeginDate.getTime() + (long)curDelay - constDelay);
curSubEndDate.setTime(curSubEndDate.getTime() + (long)curDelay - constDelay);
titlewriter.setTitleBeginDate(curSubBeginDate);
titlewriter.setTitleEndDate(curSubEndDate);
//System.out.println("old: \"" + str + "\", new: \"" + titlewriter.getTitleStr() + "\", " + (long)curDelay);
str = titlewriter.getTitleStr();
}
dout.writeBytes(str);
dout.writeBytes("\n");
};
System.out.println("Converted " + titleNo + " titles ");
}
}
class MyDate extends Date {
public MyDate() {
super();
}
public void setMilliseconds(int msec) {
if(msec <>= 1000) return;
setTime((getTime()/1000)*1000);
setTime(getTime() + msec);
}
public long getMilliseconds() {
long sec = getTime()/1000;
long msec = getTime() - sec*1000;
return msec;
}
}
class SrtTitleReader {
private String titleSrtFmt;
public SrtTitleReader() {};
public void setTitleStr(String title) {
titleSrtFmt = title.trim();
}
private MyDate getTitleDate(String title) {
int hour = Integer.valueOf(title.substring(0, 2));
int min = Integer.valueOf(title.substring(3, 5));
int sec = Integer.valueOf(title.substring(6, 8));
int msec = Integer.valueOf(title.substring(9, 12));
MyDate titledate = new MyDate();
titledate.setHours(hour);
titledate.setMinutes(min);
titledate.setSeconds(sec);
titledate.setMilliseconds(msec);
return titledate;
}
public MyDate getTitleBeginDate() {
return getTitleDate(titleSrtFmt.substring(0, 12));
}
public MyDate getTitleEndDate() {
String endtitle = titleSrtFmt.substring(12);
endtitle = endtitle.replaceAll("-->", "").trim();
return getTitleDate(endtitle);
}
}
class SrtTitleWriter {
public SrtTitleWriter() {};
private MyDate titleBeginDate = null;
private MyDate titleEndDate = null;
public void setTitleBeginDate(MyDate begindate) {
titleBeginDate = begindate;
}
public void setTitleEndDate(MyDate begindate) {
titleEndDate = begindate;
}
public String getTitleStr() {
String begintitl = String.format("%1$02d:%2$02d:%3$02d,%4$03d",
titleBeginDate.getHours(), titleBeginDate.getMinutes(),
titleBeginDate.getSeconds(), titleBeginDate.getMilliseconds());
String endtitl = String.format("%1$02d:%2$02d:%3$02d,%4$03d",
titleEndDate.getHours(), titleEndDate.getMinutes(),
titleEndDate.getSeconds(), titleEndDate.getMilliseconds());
return (begintitl + " --> " + endtitl);
}
}
Комментарии