制作 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 * 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 * Sub MMC_Done(NotifyCode As Integer) If NotifyCode = 1 Then ''如果播放完毕 MMC.Command = "stop" MMC.Command = "close" End If End Sub * Sub openTXT_Click() CommonDialog1.Filter = "txt 歌词文件(*.txt)|*.txt" txtST = openFile(0) End Sub * 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 * 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 * 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。 添加如下代码: * Sub openLRC_Click() CommonDialog1.Filter = "Lrc 歌词文件(*.lrc)|*.lrc" lrcST = openFile(0) End Sub * 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 过程代码: * 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】按纽即可。
|