تعدادي از ويديوهاي يوتيوب، خصوصا مواردي كه از Google videos به يوتيوب منتقل شدهاند، داراي زير نويس هستند. اين زير نويس هم فرمت جالبي دارد:
<?xml version="1.0" encoding="UTF-8"?>
<transcript>
<text start="23.49" dur="5.97">
&gt;&gt;Commentator: We have here today, Steve with
us whom I met not too long ago at something
</text>
...
</transcript>
ابتدا شايد بپرسيد كه اينها را چگونه ميتوان دريافت كرد. روش كار به صورت زير است:
http://video.google.com/timedtext?hl=en&v=Id&lang=en
در قسمتهاي hl و lang ، زبان مورد نظر قرار ميگيرد و قسمت v همان id معروف ويديوي يوتيوب مورد نظر است. براي مثال اگر لينك ويديوي ما http://www.youtube.com/watch?v=-PA-buwI3q4 باشد، لينك زيرنويس انگليسي هماهنگ با آن http://video.google.com/timedtext?hl=en&v=-PA-buwI3q4&lang=en خواهد بود.
البته زمانهاي اين فايل xml يك نكتهي خاص گوگلي دارد!
اگر عدد 3.4 را مشاهده كرديد يعني سه ثانيه و 400 ميلي ثانيه
اگر عدد 3.04 را مشاهده كرديد يعني سه ثانيه و 40 ميلي ثانيه
به عبارتي با قسمت اعشاري آن بايد به صورت رشته برخورد كنيد. اگر طول آن يك بود، دو صفر و اگر طول آن 2 بود، 1 صفر در جلوي آن بايد قرار گيرد تا قابل استفاده شود.
كلاس تهيه شده زير كار تبديل Xml گوگل را به Srt انجام ميدهد:
using System;
using System.Linq;
using System.Text;
using System.Web;
using System.Xml.Linq;
namespace YtSubs
{
public class GoogleXmlToSrt
{
public string ConvertXmlToSrt(string url)
{
var transcript = loadTranscript(url);
var srtBuf = new StringBuilder();
var lineNumber = 0;
foreach (var item in transcript.Root.Elements("text"))
{
lineNumber++;
srtBuf.Append(lineNumber.ToString());
var timeLine = getTimeLine(item);
srtBuf.AppendFormat("{0}{1} --> {2}{3}", Environment.NewLine, timeLine.Item1, timeLine.Item2, Environment.NewLine);
var msg = decodeText(item);
srtBuf.AppendLine(msg + Environment.NewLine);
}
return srtBuf.ToString();
}
private static XDocument loadTranscript(string url)
{
var transcript = XDocument.Load(url);
if (transcript.Root == null)
throw new InvalidOperationException("couldn't load received data.");
return transcript;
}
private static string decodeText(XElement text)
{
var textValue = text.Value.Split('\n');
var msg = textValue.Aggregate(
string.Empty, (current, line) =>
current + (HttpUtility.HtmlDecode(line.Trim()) + Environment.NewLine)
);
return msg.Trim();
}
private static int fractionalPart(string data)
{
var idx = data.IndexOf(".");
if (idx == -1) return 0;
var fractionalPart = data.Substring(idx + 1);
if (fractionalPart.Length == 1) //3.4 --> 3.400
return int.Parse(fractionalPart + "00");
if (fractionalPart.Length == 2) //3.04 --> 3.040
return int.Parse(fractionalPart + "0");
return int.Parse(fractionalPart.Substring(0, 3));
}
private Tuple<string, string> getTimeLine(XElement text)
{
var startTs = getStartTs(text);
TimeSpan endTs = getEndTs(text, startTs);
return new Tuple<string, string>(timeSpanToString(startTs), timeSpanToString(endTs));
}
private static TimeSpan getStartTs(XElement text)
{
var startData = text.Attribute("start");
if (startData == null)
throw new InvalidOperationException("This is not a valid subtitle file.");
var start = startData.Value;
var startTs = new TimeSpan(0, 0, 0, (int)Math.Truncate(double.Parse(start)), fractionalPart(start));
return startTs;
}
private static TimeSpan getEndTs(XElement text, TimeSpan startTs)
{
TimeSpan endTs;
var durData = text.Attribute("dur");
if (durData == null)
{
endTs = startTs + new TimeSpan(0, 0, 0, 3, 0);
}
else
{
var dur = durData.Value;
var durTs = new TimeSpan(0, 0, 0, (int)Math.Truncate(double.Parse(dur)), fractionalPart(dur));
endTs = startTs + durTs;
}
return endTs;
}
private static string timeSpanToString(TimeSpan lineTs)
{
return string.Format("{0}:{1}:{2},{3}",
lineTs.Hours.ToString("D2"),
lineTs.Minutes.ToString("D2"),
lineTs.Seconds.ToString("D2"),
lineTs.Milliseconds.ToString("D3"));
}
}
}
using System.IO;
namespace YtSubs
{
class Program
{
static void Main(string[] args)
{
var url = "http://video.google.com/timedtext?hl=en&v=-PA-buwI3q4&lang=en";
//var url = "subtitle.xml";
var srtBuf = new GoogleXmlToSrt().ConvertXmlToSrt(url);
File.WriteAllText("-PA-buwI3q4.srt", srtBuf);
}
}
}
مطالب تكميلي:
همه چیز درباره زیرنویس ویدئوهای گوگل