利用批次檔和vbs 腳本實現網站影片自動錄製
現在電視台基本上都有了自己的入口網站,我們可以充分利用網路的優勢來擴大本地電視台的影響力。事實上,將本地電視台的每日的王牌節目掛在網站上的做法已經成為建立電視台網站的必要組成步驟之一了。但隨之而來的問題是:每天定時所需的手工錄製過程,將給管理者帶來極大的不便。在windows 定時任務的基礎上,將批次程式與腳本程式有機的集合,就可以有效地解決這個問題。
1 :建立壓碼任務
我們將使用一台有視訊擷取卡的電腦來完成壓碼過程。雖然壓碼不是本文的重點,但還是有必要交代一下。主要就是使用helix producer plus9 建立一個壓碼參數文件,事實上它只是一個帶有rpjf 後綴的xml 文件(圖1 )。需要注意的是,音訊輸入選項有線路輸入與microphone 輸入兩種,這需要與實際的接入線路相吻合;另外,不必選擇2 pass vedio encoding 選項,選擇它除了顯示一個warning 外不會有任何效果;再者,因為現階段絕大多數的網路存取模式為撥號和dsl ,所以只需要產生56k 和384k 碼率的視訊檔案;最後,錄製完成的視訊文件,其名稱最好用日期來標識,比如: 20060301.rm 。
<?xml version=1.0 encoding=UTF-8?>
<job xmlns=http://ns.real.com/tools/job.1.0.1>
<enableTwoPass type=bool>false</enableTwoPass>
<clipInfo>
<entry>
<name>Author</name>
<value type=string>ZSTV</value>
</entry>
<entry>
<name>Copyright</name>
<value type=string>(c) ZSTV2006 </value>
</entry>
<entry>
<name>Keywords</name>
<value type=string>ZSNews[2006-03-21]</value>
</entry>
<entry>
<name>Title</name>
<value type=string>ZSNews[2006-03-21]</value>
</entry>
</clipInfo>
<input>
<captureInput>
<audioDeviceID type=string>Intel(r) Integrated Audio</audioDeviceID>
................................
我們可以建立一個名為shixian.bat 的批次檔來的呼叫上面所示的參數文件,內部具體如下:
producer -jd:/shixian/shixian.rpjf -daw -lc e,i
預設的錄製過程會即時監控音訊變化,並將它記錄到一個叫producer.log 的檔案之中,但是產生的wanging 記錄很多,很快就使log 檔案變得巨大而且可能引起錄製過程的意外中斷,所以我們可以使用-daw 參數關閉音訊監視,再用lc e,i 指明只記錄錯誤和訊息。這樣做之後,錄製過程就比較穩定了。
只要在計劃中新增每日執行shixian.bat 檔案的任務,我們就會每天得到一個相同檔案屬性和名稱的rm 檔案。這裡將每天產生一個帶有2006-03-21 屬性的、名為20060321.rm 檔案。聽起來很拗口,更糟的是這並沒有減輕管理者的工作,因為他必須每天打開伺服器來改名稱。而且即便有幸僱用了一名勤奮的管理員(他不介意每天做這樣重複的事情),但他還是沒辦法更改文件中顯示日期的屬性,在這錄製過程中已經決定了。除非…….
2 :建立修改壓碼參數檔的任務
原理很簡單:每天更新壓碼參數檔中與日期相關的xml 欄位。在這個例子裡是文件顯示日期的屬性和檔名。 以下就是用於更新日期欄位的腳本程式碼:
dim regOR
set regOR=new regexp ' 建立一個正規表示式對象
regOR.ignorecase=True ' 忽略大小寫
regOR.global=True ' 搜尋套用於整個字串
regOR.pattern=^([0-9]{1})$ ' 建立搜尋模式為單一數字表達式
dim mytime
mytime=date ' 用date 函數達到系統日期,並賦值給mydate
yy=year(mytime) ' 提取系統日期中的年份
mm=month(mytime) ' 提取系統日期中的月份
dd=day(mytime) ' 提取系統日期中的日期
if regOR.test(mm) then ' 偵測月份是否為單一數字(一月到九月)
mm=regOR.replace(mm,0$1) ' 如果是,則在月份前加上0 使其成為兩個數字
end if
if regOR.test(dd) then ' 偵測日期是否為單數字(一日到九日)
dd=regOR.replace(dd,0$1) ' 如果是,則在日期前加上0 使其成為兩個數字
end if
mytime=yy & - & mm & - & dd ' 合併年月日為yy-mm-dd 形式
dest=yy & mm & dd ' 合併年月日為yymmdd 形式
pattern1=(.*[^0-9])([0-9]{4}/-[0-9]{2}/-[0-9]{2})([^0-9]. *)
' 設定模式變數pattern1 為%d%d%d %d- %d %d -%d %d
pattern2=(.*[^0-9])([0-9]{8})([^0-9].*) ' 設定模式變數pattern2 為8 個連續數字
regOR.pattern=pattern1 ' 建立搜尋模式為pattern1
dim tempstring
Set fso = CreateObject(Scripting.FileSystemObject) ' 建立系統檔案物件
Set f = fso.CreateTextFile(d:/shixian/temp.txt, True) ' 新名為temp 的文字文件
Set fr = fso.GetFile(d:/shixian/shixian.rpjf) ' 得到編碼參數檔shixian.rpjf
Set ts = fr.OpenAsTextStream(1,-2) ' 將參數檔案以唯讀文字形式開啟
do until ts.AtEndOfStream ' 建立循環,直到參數檔讀取完畢
tempstring=ts.readline ' 以行為單位讀取參數文件
if regOR.test(tempstring) then ' 搜尋改行參數是否存在日期字段
tempstring=regOR.replace(tempstring,$1 & mytime & $3) ' 如存在,則更新
end if
regOR.pattern=pattern2 ' 建立搜尋模式為pattern2
if regOR.test(tempstring) then ' 搜尋改行參數是否存在日期字段
tempstring=regOR.replace(tempstring,$1 & dest & $3) ' 如存在,則更新
end if
regOR.pattern=pattern1 ' 重新建立搜尋模式為pattern1
f.writeline(tempstring) ' 將更新後的資料寫入temp.txt 文件
loop
ts.close '以下是關閉和註銷各個對象
f.close
set regOR=nothing
set ts=nothing
set fr=nothing
set f=nothing
set fso=nothing
要說明的是為什麼要在單數字的月份和日期前加0 。打個比方比較容易說明:如果不加0 ,那麼對於一個名為2006111.rm 的文件,它究竟是指2006 年1 月11 日還是2006 年11 月1 日呢?加0 後變成20060111.rm 就一目了然了,是前者。
以上這段腳本程式碼的具體功能是將參數檔案中的資料以行為單位匯入到一個臨時的文字檔案中,即時監視與時間相關的xml 欄位並加以更新,最後在產生一個temp.txt 的檔案中。之後我們要做的無非就是用批次檔呼叫腳本,再刪除舊的參數文件,最後將temp.txt 重新命名為參數檔。
這就是update.bat 批次檔中的程式碼:
@echo off
d:/shixian/update.vbs
if exist d:/shixian/shixian.rpjf del d:/shixian/shixian.rpjf
if exist d:/shixian/temp.txt rename d:/shixian/temp.txt shixian.rpjf
和第一節一樣,還是要將這個update.bat 的批次檔加入到排程與任務中,以便每日定時啟動。
3 :建立自動傳輸任務
為了確保穩定,通常壓碼伺服器與網站伺服器是分離的,這需要我們每天將錄製的視訊檔案傳輸到網站伺服器上。批次檔中的ftp 指令可以完美的實現這項功能。
以下就是transfer.bat 批次中的程式碼:
@echo off
ftp -s:media.txt
if exist d:/shixian/shixian20060321.rm del d:/shixian/shixian20060321.rm
考慮到SCSI 硬碟驚人的價格,壓碼伺服器的硬碟空間不必太大,最後一行的作用就是刪除壓碼伺服器中的視訊文件,以節省空間。 Media.txt 是一個ftp 參數文件,其中記錄了ftp 登陸伺服器的名稱、使用者名稱、密碼和相關的操作,具體形式如下:
open / 伺服器名稱或IP 位址/
/ 使用者名稱/
/ 用戶密碼/
put / 要傳輸的檔案名稱/
quit
很明顯,以上的各段程式碼中不乏需要更新的日期文字表達式。同樣的道理,我們也需要使用一個類似的更新腳本,具體程式碼就不重複了。
4 :一些改進的意見
1 :使用media player 也可實現壓碼的功能。
2 :在更新腳本中,用在宣告和登出物件上的程式碼有好幾行,如果使用perl 可以大為簡化。因為是perl 提供了一系列操作符號來實現正規表示式的功能,而事實上perl 就是為了處理文字而生的。
open(RPJF,<c:/code/10161.rpjf) or die(can not open because of $!/n);
open(TEMP,>c:/code/temp.txt) or die(can not open because of $!/n);
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=localtime();
$mday=sprintf(%.2d,$mday);
$mon=sprintf(%.2d,$mon+1);
$year+=1900;
$timerF=$year.$mon.$mday;
$timerS=$year.-.$mon.-.$mday;
while(<RPJF>){
chomp();
$_=~s/(.*)([0-9]{8})(.*)/$1$timerF$3/;
$_=~s/(.*)([0-9]{4}/-[0-9]{2}/-[0-9]{2})(.*)/$1$timerS$3/ ;
print TEMP $_/n;
}
close(RPJF);
close(TEMP);
3 :使用磁碟映射能夠更方便的實作檔案的傳輸,不過需要考慮安全性問題。