Skip to content

Instantly share code, notes, and snippets.

@notyy
Created February 20, 2012 13:55
Show Gist options
  • Save notyy/1869326 to your computer and use it in GitHub Desktop.
Save notyy/1869326 to your computer and use it in GitHub Desktop.
2D字幕文件转3D
本程序逻辑如下:
1、列出当前目录下所有后缀名为srt的文件,过滤掉其中文件名以-3D结尾的文件
2、对每个符合条件1的文件,读取其内容,通过在字幕内容中加入坐标偏移量,使之能在左右屏的3D电视上正常播放
3、srt文件格式
1、文件由多个段落组成,段落之间以空行分隔
2、每段落中的内容由3部分组成
1、序号
2、时间量
3、字幕内容
4、转换逻辑是将原字幕内容分别在前面加上偏移量{\pos(96,255)\fscx50}和{\pos(288,255)\fscx50},变成两段内容,一个序号保持不变,位置也不变,而另一段必须加到原内容最后,序号递增
举例如下:
1
00:00:46,171 --> 00:00:48,340
《每日快讯》
2
00:00:56,181 --> 00:00:57,015
请稍等
经过转换后应为
1
00:00:46,171 --> 00:00:48,340
{\pos(96,255)\fscx50}《每日快讯》
2
00:00:56,181 --> 00:00:57,015
{\pos(96,255)\fscx50}请稍等
3
00:00:46,171 --> 00:00:48,340
{\pos(288,255)\fscx50}《每日快讯》
4
00:00:56,181 --> 00:00:57,015
{\pos(288,255)\fscx50}请稍等
-------------代码------------------------------------
import java.io._
import scala.io._
import scala.collection.JavaConverters._
object MainApp extends App {
def files23D() {
val files = new File(".").listFiles() filter isValidFile
files map to3D
}
def isValidFile(f: File) = {
f.isFile() && !(f.getName.endsWith("-3D.srt")) && f.getName.endsWith(".srt")
}
def to3D(f: File) {
val srcFileName = f.getName.take(f.getName.length - ".srt".length)
val toFile = new File("./" ++ srcFileName ++ "-3D" ++ ".srt")
toFile.createNewFile()
val writer = new BufferedWriter(new FileWriter(toFile))
writer.write(convert(Source.fromFile(f).getLines))
writer.flush()
writer.close()
}
case class Section(id: Option[String], timeline: Option[String], contents: Option[String])
def convert(lines: Iterator[String]): String = {
val sections = extractSections(lines).tail.reverse
val maxId = sections.length
val offseted = sections map (offset(maxId, _))
val resultSections = fst(offseted) ++ snd(offseted)
(resultSections map (sectionToString)).mkString
}
def extractSections(strIter: Iterator[String]): List[Section] = {
strIter.foldLeft(List[Section]()) { (rsSections, line) =>
(rsSections, line) match {
case (List(), l) => Section(Some(l), None, None) :: List()
case (Section(Some(id), None, None) :: ss, l) => Section(Some(id), Some(l), None) :: ss
case (Section(Some(id), Some(timel), None) :: ss, l) => Section(Some(id), Some(timel), Some(l)) :: ss
case (Section(Some(id), Some(timel), Some(content)) :: ss, l) if (!l.isEmpty()) => Section(Some(id), Some(timel), Some(content ++ "\n" ++ l)) :: ss
case (ss, l) if (l.isEmpty()) => Section(None, None, None) :: ss // if a blank line
case (Section(None, None, None) :: ss, l) => Section(Some(l), None, None) :: ss
}
}
}
def offset(mid: Int, sec: Section): (Section, Section) = (mid, sec) match {
case (mid, Section(Some(id), Some(timel), Some(contents))) => {
val left = Section(Some(id), Some(timel), Some("{\\pos(96,255)\\fscx50}" ++ contents))
val newId: Int = id.toInt + mid
val right = Section(Some(newId.toString()), Some(timel), Some("{\\pos(288,255)\\fscx50}" ++ contents))
(left, right)
}
case (_, Section(None, None, None)) => throw new IllegalArgumentException("error offset")
}
def sectionToString(sec: Section): String = sec match {
case (Section(Some(id), Some(timel), Some(contents))) => id ++ "\n" ++ timel ++ "\n" ++ contents ++ "\n\n"
case _ => throw new IllegalArgumentException("error sectionToString")
}
def fst[A, B](l: List[(A, B)]): List[A] = l map (_._1)
def snd[A, B](l: List[(A, B)]): List[B] = l map (_._2)
override def main(args: Array[String]) {
files23D()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment