加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

如何用excel把smi字幕转成srt字幕(By Kiseigo)

(2009-03-30 17:01:33)
标签:

smi

srt

字幕

excel

vba

老友记

转换

it

英语

学习

剧本

分类: 英语

看了《老友记》,很喜欢,所以去找字幕,结果只是找到了中文的srt字幕,还有smi格式的英文字幕,打开一看,差不多的格式,很容易读懂,所以花了几天时间,用vba写了一个转换的东西,老爱好,还是在excel中,不需要安装vb6,不需要安装vs2005,绿色的,^_^

 

运行过了,在winxp下excel2003下通过。

作者:kiseigo 日期:2003.03.30

 

Option Explicit

'此过程实现smi字幕转换成srt字幕
Sub ConvertSMItoSRT()
    Call SMItoSRT("D:\FriendsS01E01.smi", "D:\FriendsS01E01.srt")
End Sub

'转换smi文本成为srt文本 2009.04.03 修改
'pathSMI: 输入的路径,smi文件的完整路径,比如 "D:\FriendsS01E02.smi"
'pathSRT: 输出路径,srt文件的完整路径(如果不存在就新建,如果已经存在就删除,然后再新建),比如 "D:\FriendsS01E02.srt"
Private Sub SMItoSRT(pathSMI As String, pathSRT As String)

'SMI的格式如下:
'<SYNC Start=1601><P Class=ENCC>
'The One Where It All Began (Pilot)
'<SYNC Start=5059><P Class=ENCC>&nbsp;
'<SYNC Start=55422><P Class=ENCC>
'There 's nothing to tell.<br>
'It 's just some guy I work with.
'<SYNC Start=59256><P Class=ENCC>&nbsp;


'srt的格式如下:
'1
'00:00:55,422 --> 00:00:59,256
'没什么好说的!
'他不过是我的同事!
'
'2
'00:00:59,459 --> 00:01:01,586
'少来了,你和那个人一起出去!
   
    ' 步骤1:读取数据到LinesSource()中,为了防止出意外,先不分析数据
    Dim fileContents As String
    Dim LinesSource() As String
    Dim nfSMI As Integer
   
    nfSMI = FreeFile
    Open pathSMI For Binary As #nfSMI
        fileContents = Space(LOF(nfSMI))
        Get #nfSMI, , fileContents
    Close nfSMI
    LinesSource = Split(fileContents, vbCrLf)
   
   '步骤2:对数据LinesSource()进行初步分析,得到TimeContent(),暂时不保存
    Dim data() As TimeContent
    ReDim Preserve data(100) '一次显示的字幕最多5行了
    Dim nParag As Integer '第几段,从0开始
    Dim nTmp01 As Integer '临时变量01
    Dim nTmp02 As Integer
    Dim nIndexTmp As Integer '本段落的第几行字幕,从0开始
    Dim blnGetTheEndOfParag As Boolean '=ture, 找到了此段落的终点. = false, 没有找到终点
    blnGetTheEndOfParag = True
  
    Dim i As Integer
    Dim j As Integer
    Dim k As Integer
   
    For i = 0 To UBound(LinesSource)
        LinesSource(i) = Replace(LinesSource(i), "<br>", "")
        If UBound(data) <= nParag Then
            ReDim Preserve data((UBound(data) + 100))
        End If
      
        '找起点
        If blnGetTheEndOfParag = True And Left$(LinesSource(i), 5) = "<SYNC" And Right$(LinesSource(i), 5) = "ENCC>" Then
            data(nParag).nBegin = i
            nTmp01 = InStr(LinesSource(i), "Start=") + 6
            nTmp02 = InStr(LinesSource(i), "><P") - nTmp01
            If nTmp02 >= 1 Then
                data(nParag).nTimeBegin = Mid$(LinesSource(i), nTmp01, nTmp02) '找到了此次字幕的开始时间
            End If
            blnGetTheEndOfParag = False
        End If
      
        '找终点
        If blnGetTheEndOfParag = False And Left$(LinesSource(i), 5) = "<SYNC" And Right$(LinesSource(i), 11) = "ENCC>&nbsp;" Then
            data(nParag).nEnd = i
            nTmp01 = InStr(LinesSource(i), "Start=") + 6
            nTmp02 = InStr(LinesSource(i), "><P") - nTmp01
            If nTmp02 >= 1 Then
                data(nParag).nTimeEnd = Mid$(LinesSource(i), nTmp01, nTmp02) '找到了此次字幕的结束时间
                data(nParag).strTimeHHmmssFromTo = GetHHmmssFrom1000ss(data(nParag).nTimeBegin) & " --> " & GetHHmmssFrom1000ss(data(nParag).nTimeEnd)
            End If
            blnGetTheEndOfParag = True
          
        End If
      
        '读取字幕的内容
        If blnGetTheEndOfParag = True And data(nParag).nBegin >= 1 And data(nParag).nEnd >= 1 And data(nParag).nEnd - data(nParag).nBegin - 2 >= 0 Then
            ReDim data(nParag).strContents(data(nParag).nEnd - data(nParag).nBegin - 2)
          
            For j = data(nParag).nBegin + 1 To data(nParag).nEnd - 1
                data(nParag).strContents(j - data(nParag).nBegin - 1) = LinesSource(j)
            Next j
          
            nParag = nParag + 1 '找到尾时才给它加1
        End If
    Next
  
    ReDim Preserve data(nParag - 1) 'data(390) = null ing
  
    '步骤3:最终分析TimeContent()并保存数据到指定的文本
    Dim nfSRT As Integer
    nfSRT = FreeFile
  
    Dim iNum As Integer '段落的序号,表示第几段,从1开始记数
    iNum = 1
    'Dim strTimeFromTo As String '开始和结束的时间 "00:00:55,422 --> 00:00:59,256"
    Dim strContent As String '段落的内容
  
    Open pathSRT For Append As #nfSRT
        For j = 0 To UBound(data)
            Print #nfSRT, CStr(j + 1) '序号
            Print #nfSRT, data(j).strTimeHHmmssFromTo '开始和结束的时间 "00:00:55,422 --> 00:00:59,256"
            For k = 0 To UBound(data(j).strContents) '内容(可能多行)
                Print #nfSRT, data(j).strContents(k)
            Next k
            Print #nfSRT, "" '空行做为段落的间隔
        Next
    Close #nfSRT
  
    MsgBox "恭喜,成功转换成srt格式."
    End
  
Err:
    MsgBox "错误的行号是: " & i
End Sub

'把1000毫秒为单位的时间转换成时分秒为单位的时间
'输入:毫秒为单位的数据,如 64597
'输出:00:01:04,597
Public Function GetHHmmssFrom1000ss(ss As Long) As String
    Dim ssHHmmss As String
  
    Dim nHH As Integer '小时
    nHH = Int(ss / 1000 / 3600)
    Dim nMM As Integer '分
    nMM = (Int(ss / 1000 / 60)) Mod 60
    Dim nSs As Integer '整秒数
    nSs = Int(ss / 1000) Mod 60
    Dim nSs1000 As Integer '不够整秒数的毫秒数
    nSs1000 = Val(Right$(CStr(ss), 3))
    ssHHmmss = Format(CStr(nHH), "00") & ":" & Format(CStr(nMM), "00") & ":" & Format(CStr(nSs), "00") & "," & Format(CStr(nSs1000), "00")
  
    GetHHmmssFrom1000ss = ssHHmmss
End Function

 

'模块中的代码:

Public Type TimeContent '时间,开始和结束的行数,和内容
    nParagraph As Integer '段落,第几段,从1开始
    nBegin As Integer '开始的行数,第一行是0行
    nEnd As Integer '结束的行数
    nTimeBegin As Long '开始的时间,单位是1000毫秒,比如:66833表示00:01:06,833
    nTimeEnd As Long '结束的时间,比如: "<SYNC Start=69358><P Class=ENCC>&nbsp;" 中的69358表示00:01:09,358
    strTimeHHmmssFromTo As String '开始时间到结束时间 srt格式,如:00:29:27,465 --> 00:29:29,831 时分秒,毫秒
    strContents() As String '多行文字的内容,从0开始
End Type

 

需要《老友记》中英文对照的,想学习英文口语的,请留下email,保证发送给你。

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有