回 帖 发 新 帖 刷新版面

主题:[原创]制作 smi 字幕文件的方法

制作 smi 字幕文件的方法

  微软的媒体播放器 wmplayer 使用 smi 字幕文件,可以使字幕与唱词同步。先来了解一下 smi 文件的基本结构:

<SAMI>
<head>
<style type="text/css"><!--
p     {font-size:24pt;font-family:楷体_GB2312;}
.FRCC {lang: ZH-CN;}-->
</style>
</head>
<body>
<sync start=10><p class=EGCC>敖包相会(歌手:张振富、耿莲凤)
<sync start=25158><p class=EGCC>(男)十五的月亮升上了天空哎
……
</body>
</SAMI>

  可以看出,smi 文件是用超文本语言写的。注意二点:
1.“start=****”时间参数,是以毫秒为单位的。
2.“{font-size:24pt;font-family:楷体_GB2312;}”这里只有2个参数,分别是字体大小和字体名称。还可以写成这样:

 { background-color: #000000; text-align: center; font-size: 24pt; font-family: 宋体; font-weight: bold; }

参数1:可选,字幕条的背景颜色为黑色,缺省为黑色。
参数2:可选,文本显示位置为窗口中央,缺省为左。
参数3:字体大小。
参数4:字体名称。
参数5:可选,字体重量为粗体。

  参数的顺序没有严格要求,但必须以分号分隔。
  下面介绍两种制作 smi 文件的方法。

一、使用 txt 歌词文件
  如果我们用 MMControl 控件制作了一个播放器,利用该控件的 Position 属性,我们就可以实时制作 smi 字幕文件。当然,你还必须要有同名的 txt 歌词文件,这可以在网上下载,也可以自己编制。
  MMControl 控件的 Position属性的作用是:根据指定的 TimeFormat 返回已打开的设备的位置,一般用四字节表示,只读。在使用 Position 属性之前,要先设置属性 TimeFormat=0,这样 Position属性返回的时间单位就是毫秒。
  新建一个工程,在窗体上添加一个 MMControl 控件(将其名称改为MMC),一个 CommonDialog 控件、三个按纽、一个标签(标签的作用是显示当前的歌词),属性设置为:

MMControl 控件:在属性页中将所有的自带按纽均设置为无效和不可见。
三个按纽控件的名称与标题相同,分别为:openTXT、playMCI、txtTOsmi。

  代码如下:

Option Explicit

Dim lrcST As String, smiST As String, txtST As String

Private Sub playMCI_Click()
CommonDialog1.Filter = "*.mp3;*.wma|*.mp3;*.wma"
With MMC
  .FileName = openFile(1)
  .Command = "Open"
  .TimeFormat = 0 '时间格式为毫秒
  .Notify = True  '打开通知
  .Command = "play"
End With
End Sub

Private Sub MMC_Done(NotifyCode As Integer)
If NotifyCode = 1 Then  '如果播放完毕
  MMC.Command = "stop"
  MMC.Command = "close"
End If
End Sub

Private Sub openTXT_Click()
CommonDialog1.Filter = "txt 歌词文件(*.txt)|*.txt"
txtST = openFile(0)
End Sub

Private Sub txtTOsmi_Click()
Dim k1 As Long, t As Long

If Len(txtST) < 2 Then
  saveFile
  Exit Sub
End If

t = MMC.Position '取得播放时间位置
k1 = InStr(txtST, "~")
Label1 = Left$(txtST, k1 - 1)
txtST = Mid$(txtST, k1 + 1)
smiST = smiST & "<sync start=" & t & "><p class=EGCC>" & Label1.Caption & "~"
End Sub

Private Function openFile(bj As Boolean) As String
On Error GoTo 100
CommonDialog1.Flags = &H1808
CommonDialog1.DialogTitle = "打开文件"
CommonDialog1.ShowOpen
If Dir(CommonDialog1.FileName) = "" Then Exit Function
If bj Then openFile = CommonDialog1.FileName: Exit Function
  
Dim z As String, st As String
Open CommonDialog1.FileName For Input As #1
Do Until EOF(1)
  Line Input #1, z
  If Len(z) > 0 Then st = st & z & "~" '用这个不常用的字符"~"作为歌词句的分隔符
Loop
smiST = "": openFile = st
100
Close
End Function

Private Sub saveFile() '保存smi文件
On Error GoTo 100
CommonDialog1.DialogTitle = "保存"
CommonDialog1.Filter = "smi 文件(*.smi)|*.smi|"
CommonDialog1.Flags = &H200A
CommonDialog1.ShowSave
If CommonDialog1.FileName = "" Then Exit Sub
Dim st As String
smiST = "<SAMI><head>" & vbCrLf & "<style type=" & Chr(34) & "text/css" & Chr(34) & _
  "><!--" & vbCrLf & "p     {font-size:24pt;font-family:楷体_GB2312;}" & vbCrLf & _
  ".FRCC {lang: ZH-CN;}" & "--></style></head>" & vbCrLf & "<body>" & vbCrLf & _
  smiST & "</body></SAMI>"
st = Replace(smiST, "~", vbCrLf)
Open CommonDialog1.FileName For Output As #1
Print #1, st
100
Close
End Sub

  使用方法:首先点击【openTXT】,打开有关的 TXT 歌词文件,然后点击【playMCI】,这时候你就要认真听,当听到歌手将要唱到下一句时,就用鼠标点一下【txtTOsmi】,这样边听边点击地操作,一直到整首歌曲唱完,最后保存。如果不小心,某一句的时间误差太大,还可以用记事本打开 smi 文件修改。


二、利用 lrc 文件转换
  这个就要简单多了,因为 lrc 文件已经包括了时间参数。还有个好处是可以批量操作。
  在窗体上再添加二个按纽,名称与标题相同,分别为:openLRC、lrcTOsmi。
  添加如下代码:

Private Sub openLRC_Click()
CommonDialog1.Filter = "Lrc 歌词文件(*.lrc)|*.lrc"
lrcST = openFile(0)
End Sub

Private Sub lrcTOsmi_Click()
Dim k1 As Long   '歌词句在文件中的起始位置
Dim k2 As Long   '歌词句的长度
Dim t As Long
Dim s As String, z As String

k1 = 1: k2 = InStr(k1, lrcST, "~")
Do While k2 > 0                                 '如果有"~"字符就继续循环
  z = Mid$(lrcST, k1, k2 - k1)                  '从歌词句中取出含有方括号的字串
  k1 = k2 + 1                                   '设置下一歌词句在文件中的起始位置
  s = Mid$(z, 2, InStr(z, "]") - 2)             '取出去掉了方括号的字串
  If IsNumeric(Left$(s, 2)) Then                '如果是时间字串
    t = Val(s) * 60000 + Val(Mid$(s, 4)) * 1000 '将时间字串转换为毫秒
    smiST = smiST & "<sync start=" & t & "><p class=EGCC>" & Mid$(z, InStr(z, "]") + 1) & "~"
  End If
  k2 = InStr(k1, lrcST, "~")
Loop

saveFile
End Sub

  使用方法:首先点击【openLRC】,打开有关的 lrc 歌词文件,然后点击【lrcTOsmi】,几乎是眨
眼间,就已经转换完毕,最后保存。


参考:
  smi 字幕可以在 wmplayer 播放器窗口显示二行,相当于预告下一句的内容。这两行的颜色可以不相同,例如:

……
<sync start=10><p class=EGCC><font color=#FFFFFF>十送红军(江西民歌)</font><br><font color=#6888E0>一送(里格)红军,(介支个)下了山,</font>
<sync start=17180><p class=EGCC><font color=#6888E0>秋风(里格)细雨,(介支个)缠绵绵。</font><br><font color=#FFFFFF>一送(里格)红军,(介支个)下了山,</font>
……

  代码中超文本标记的意义:

<font color=#FFFFFF>:定义紧随其后的字体颜色,颜色可以是6位16进制数值(前面要加一个“#”字符),也可以是超文本语言的颜色常数(相当于 VB 的颜色常数),例如:black(黑色)、olive(橄榄色)、teal(鸭绿)等等,共 16 种颜色。

</font>:先前有关字体的定义到此为止,后面如果没有再次定义,将恢复默认定义。

<br>:相当于 VB 中的回车换行符。


  大家如有兴趣,请自行研究制作方法,并不难。


附:在自制播放器中使用 smi 字幕文件的方法

  在窗体上再添加一个计时器控件,Inteval = 20,Enabled = False。
  歌词就使用刚制作好的 smi 文件(当然,你也可以再增加一个【openSMI】按纽,请自编代码)。
  增加一个模块级变量:

Dim BJMode As Boolean  'True-显示歌词;False-制作歌词
Dim posit As Long      'smi文件中的时间参数位置

  在 Sub saveFile() 过程后面增加一句:BJMode = True
  在 Function openFile 函数后面增加一句:BJMode = False
  在 Sub playMCI_Click 过程后面增加一句:If BJMode Then posit = 1: Timer1.Enabled = True
  编写 Timer1_Timer 过程代码:

Private Sub Timer1_Timer()
Dim t As Long, k1 As Long, k2 As Long
If posit > Len(smiST) - 15 Then Timer1.Enabled = False: Exit Sub
k1 = InStr(posit, smiST, "start=")     '查找时间字串
t = Val(Mid$(smiST, k1 + 6, 8))        '取出时间
If Abs(MMC.Position - t) < 200 Then    '如果歌词与播放进度的时间差小于200毫秒
  k1 = InStr(k1, smiST, "EGCC>")       '查找歌词文本起点
  k2 = InStr(k1, smiST, "~")           '查找歌词文本终点
  Label1 = Mid$(smiST, k1 + 5, k2 - k1 - 5) '取出歌词字串显示在标签上
  posit = k2 + 1
End If
End Sub

  使用方法:制作完成 smi 文件后,再点击【playMCI】按纽即可。


2011.6.27

回复列表 (共4个回复)

沙发

大哥人真的很好,水平也很高,总想寻找的高手找到了

板凳

[url=http://www.cheapreplicawatche.co.uk/]replica watches[/url]
[url=http://www.cheapreplicawatche.co.uk/]replica watches UK[/url]
[url=http://www.cheapreplicawatche.co.uk/]Fake watches[/url]
[url=http://www.cheapreplicawatche.co.uk/]Rolex Replica[/url]
[url=http://www.cheapreplicawatche.co.uk/best-replica-bell-ross-watches-349.html]Bell & Ross Watches[/url]
[url=http://www.cheapreplicawatche.co.uk/best-replica-breitling-watches-312.html]Breitling Watches[/url]
[url=http://www.replicahause.org.uk]Replica Watches[/url]
[url=http://www.cheapreplicawatche.co.uk/best-replica-omega-watches-170.html]Omega Watches[/url]
[url=http://www.cheapreplicawatche.co.uk/best-replica-panerai-watches-292.html]Panerai Watches[/url]
[url=http://www.cheapreplicawatche.co.uk/best-replica-patek-philippe-watches-415.html]Patek Philippe Watches[/url]
[url=http://www.cheapreplicawatche.co.uk/best-replica-rolex-watches-143.html]Rolex watches[/url]
[url=http://www.cheapreplicawatche.co.uk/best-replica-tag-heuer-watches-166.html]Tag Heuer Watches[/url]
[url=http://www.cheapreplicawatche.co.uk/best-replica-uboat-watches-99.html]U-Boat Watches[/url]
[url=http://www.chanelhandbagsale.net/]Chanel Handbags[/url]
[url=http://www.chanelhandbagsale.net/]Replica Chanel[/url]
[url=http://www.chanelhandbagsale.net/]Chanel Replicas[/url]
[url=http://www.chanelhandbagsale.net/]Chanel on Sales[/url]

3 楼

顶楼主
[url=http://www.tbstore88.com][color=#ffffff]万ai可[/color][/url][color=#ffffff] www.tbstore88.com [/color]
[url=http://www.fjxdyy.com][color=#ffffff]阴jing增大[/color][/url][color=#ffffff] www.fjxdyy.com[/color]
[url=http://www.haohanwangluo.com][color=#ffffff]阴jing增大[/color][/url][color=#ffffff] www.haohanwangluo.com[/color]
[url=http://www.buyintb.com][color=#ffffff]万ai可[/color][/url][color=#ffffff] www.buyintb.com[/color]
[url=http://www.zxgrow.com][color=#ffffff]卡王[/color][/url][color=#ffffff] www.zxgrow.com[/color]
[url=http://www.hengxingpaper.com][color=#ffffff]充qi娃娃[/color][/url][color=#ffffff] www.hengxingpaper.com[/color]
[url=http://www.hlddesy.com][color=#ffffff]蹭网卡[/color][/url][color=#ffffff] www.hlddesy.com[/color]
[url=http://www.eastshopping.net][color=#ffffff]丰xionf秘籍[/color][/url][color=#ffffff] www.eastshopping.net[/color]
[url=http://www.JSKMVCHINA.COM][color=#ffffff]怎么样才能生儿子[/color][/url][color=#ffffff] www.JSKMVCHINA.COM[/color]
[url=http://www.szyuantaidz.com][color=#ffffff]脚qi[/color][/url][color=#ffffff] www.szyuantaidz.com[/color]

4 楼

Major League Baseball "45" number. So then [url=http://www.cheapjordanforsale.us/air-jordan-4-retro-c-4.html]retro jordan 4[/url] shoes followed by No. 45 embroidered white line no.3, 5000 dollar fines dispute In the second game of the Eastern Conference [url=http://www.cheapjordanforsale.us/air-jordan-6-retro-c-6.html]retro jordan 6[/url] semifinals, the Father re-donned the jersey number "23", scored 38 points, but the foot wear or [url=http://www.cheapjordanforsale.us/air-jordan-7-retro-c-8.html]retro jordan 7[/url] embroidered with "45" was too black and white [url=http://www.cheapjordanforsale.us/air-jordan-9-retro-c-9.html]retro jordan 9[/url], then the Bulls away combat, black and white home color [url=http://www.cheapjordanforsale.us/air-jordan-10-retro-c-10.html]retro jordan 10[/url] and away the color does not match, so the Father was also fined $ 5,000 per game, the Father suddenly re-wear jersey No. 23, again by a [url=http://www.cheapjordanforsale.us/air-jordan-11-retro-c-11.html]retro jordan 11[/url] fine of $ 25,000 per game. concord directly translated into "Concord grapes", varieties of Americas grapes, [url=http://www.cheapjordanforsale.us/air-jordan-11-retro-c-11.html]jordan 11 Concord[/url] crystal outsole echoes the color with purple soles, while the color name from the soles of purple the no.5, hot on sale very terrible [url=http://www.cheapjordanforsale.us/air-jordan-12-retro-c-12.html]retro jordan 12[/url] finally listed, each Offer shops outside there are people waiting in line, some people even crushed glass [url=http://www.cheapjordanforsale.us/air-jordan-13-retro-c-13.html]retro jordan 13[/url] doors across the security downtown into the store to try to steal these shoes, in order to buy it at all costs, its all crazy!

我来回复

您尚未登录,请登录后再回复。点此登录或注册