星期日, 10月 30, 2011

ann2srt v0.3

出乎意料之外的,ann2srt v0.2 的英文發布網誌得到了不少使用者回應。反觀中文版的對應發布文章反而靜悄悄...

言歸正傳,感謝在英文網誌上回應並協助測試的讀者 L,ann2srt script 修正了在某些英文註解中會遇到的特殊狀況(例如註解中有換行字元和半形逗號),以及在 Cygwin 環境下因為混用 DOS 與 UNIX 格式的換行字元造成程式執行錯誤的問題,因此釋放出 0.3 版。雖然這些修正其實在上週就完成了,且在上週末經過測試確認可以在 Linux 和 Cygwin 下執行無誤,不過實在是太懶惰了,所以一直沒有正式釋放出來...


廢話不多說,因為也想不出有啥廢話可以繼續扯下去,所以以下就是 v0.3 的原始碼:


#!/bin/bash
#
# Convert the youtube annotation into SRT subtitle
#
# By Shang-Feng Yang
# Version: 0.3
# License: GPL v3
#
# Changelog:
# * v0.3 (Oct/19/2011):
# - Fix the parsing errors caused by comma and newline characters in
# some English annotations
# - Adding transparent dos2unix conversion for compatibility under Cygwin
# * v0.2 (Jan/19/2011):
# - Sort the annotations using the "begin" time as key
# - Minor bugs fixing
# * v0.1 (Dec/7/2010):
# - Initial release


ANN=$1
SRT=$(basename ${ANN} .xml).srt
IFS=$'\n'
I=0

function usage() {
echo -e "Usage:\n"
echo -e "\t$(basename $0) ANNOTATION_FILE\n"
}

function parseXML() {
cat ${ANN} | tr -d '\r' |tr '\n' ' ' | xmlstarlet sel -t -m 'document/annotations/annotation' -v 'TEXT' -o '|' -m 'segment/movingRegion/rectRegion' -v '@t' -o '|' -b -n | tr -d '\r'
}

function reformatTime() {
local H=$(echo $1 |cut -d ':' -f 1)
local M=$(echo $1 |cut -d ':' -f 2)
local S=$(echo $1 |cut -d ':' -f 3)
printf '%02d:%02d:%06.3f' ${H} ${M} ${S} |tr '.' ','
}

function time2sod() {
# Convert time in HH:MM:SS.SSS format into second-of-the-day value
local SOD=$(echo $1 | awk -F ":" '{printf("%f\n", $1*3600+$2*60+$3);}')

echo ${SOD}
}

[ "x${ANN}" = "x" ] && { usage; exit 1; }
[ -f ${ANN} ] || { usage; exit 1; }
[ -f ${SRT} ] && rm ${SRT}
[ -f ${SRT}.tmp ] && rm ${SRT}.tmp

for LINE in $(parseXML); do
C=$(echo ${LINE} |cut -d '|' -f 1)
B=$(echo ${LINE} |cut -d '|' -f 2)
E=$(echo ${LINE} |cut -d '|' -f 3)
echo "$(time2sod ${B})#${B}#${E}#${C}" >> ${SRT}.tmp
done

grep "###" ${SRT}.tmp && {
echo "\"${ANN}\" has no valid annotation!" >&2
rm ${SRT}.tmp
exit 1
}

for LINE in $(cat ${SRT}.tmp|sort -n -t '#'); do
(( I++ ))
C=$(echo ${LINE} |cut -d '#' -f 4)
B=$(reformatTime $(echo ${LINE} |cut -d '#' -f 2))
E=$(reformatTime $(echo ${LINE} |cut -d '#' -f 3))
echo -e "${I}\n${B} --> ${E}\n${C}\n" >> ${SRT}
done

rm ${SRT}.tmp


為了避免因為複製貼上造成的錯誤,所以以上程式也可以從這邊下載:
http://dl.dropbox.com/u/1382119/tmp/ann2srt

基本上 v0.3 和 v0.2 比起來,並沒有太多的改變,只有為了避開註解中出現半形逗號的狀況,所以把本來當作中介格式的 CSV 格式的分隔符號,由逗號改成了 "|" 符號,並且使用 tr 移除沒必要的換行字元和把 DOS 的換行字元轉換成 UNIX 格式。由於 DOS 轉 UNIX 格式實際上只是摻除 carrier return 字元 ("\r" 字元),所以這樣的修改並不會影響在 Linux 下的執行。

繼續閱讀全文