‏نمایش پست‌ها با برچسب SubtitleTools. نمایش همه پست‌ها
‏نمایش پست‌ها با برچسب SubtitleTools. نمایش همه پست‌ها

۱۳۹۰/۱۱/۱۴

استفاده از قابليت Speech Recognition ويندوز 7 براي توليد زيرنويس انگليسي


از ويندوز ويستا به بعد، ويندوز به صورت توكار داراي يك موتور تشخيص صدا شده است كه در اين مسير قابل مشاهده مي‌باشد:
Control Panel\Ease of Access\Speech Recognition

اين سرويس از طريق اسمبلي استاندارد System.Speech در دات نت فريم ورك قابل استفاده است كه اكنون با برنامه‌ي Subtitle tools يكپارچه شده است.


يكي از خصوصيات مفيد اين موتور تشخيص صدا، امكان دريافت فايل‌هاي صوتي نيز مي‌باشد. فايل صوتي دريافتي بايد مطابق يكي از فرمت‌هاي پشتيباني شده توسط آن، تهيه شود؛ كه اين مورد را ذيل قسمت Supported audio formats شكل فوق مي‌توانيد مشاهده كنيد.
براي نمونه توسط برنامه AoA Audio Extractor Basic، مي‌توان اين تبديلات را انجام داد و يكي از تنظيمات قابل قبول توسط موتور Speech Recognition ويندوز 7 را در تصوير ذيل مي‌توانيد مشاهده كنيد: (و در غيراينصورت هيچ خروجي را نخواهيد گرفت؛‌ خيلي مهم!)


پس از انتخاب و گشودن فايل صوتي در برنامه Subtitle tools (كليك بر روي دكمه Open WAV‌ در اينجا) و سپس كليك بر روي دكمه‌ي Recognize يا Start ، كار موتور Speech Recognition ويندوز شروع شده و برنامه هم در اينجا از فرصت استفاده كرده و دريافتي نهايي را تبديل به ركوردهاي فايل زيرنويس مي‌كند كه نمونه‌اي از آن‌را در شكل فوق مي‌توانيد ملاحظه كنيد.


نكاتي در مورد استفاده بهينه از موتور تشخيص صداي ويندوز:

الف) براي آزمايش برنامه، يك فايل voice را از اينجا دريافت كنيد. اين فايل voice از همان سري مترو PluralSight تهيه شده است.
ابتدا موتور تشخيص صداي انتخابي را بر روي حالت US قرار داده و تست كنيد. در ادامه يكبار هم برروي حالت UK قرار دهيد و كار تشخيص صدا را آغاز نمائيد.
نتايج كاملا متفاوت خواهند بود و با توجه به لهجه انگليسي گوينده، تشخيص‌هاي حالت UK، به واقعيت نزديكتر هستند. اين مورد را در گزينه‌ي Average confidence هم مي‌توانيد مشاهده نمائيد. مثلا در اينجا موتور تشخيص صدا در كل به 60 درصد خروجي توليدي‌اش اطمينان دارد و مابقي ... آنچنان اعتباري ندارند.
مثلا متن صحيح سطر چهارم در تصوير فوق بايد «when they are not in the foreground» باشد!

ب) تنظيمات Timeouts
اگر به فايل voice فوق دقت كنيد، گوينده يك نفس از ابتدا تا انتها صحبت مي‌كند. اينجا است كه به كمك مقادير Silence timeout ، مي‌توان تعداد ركوردها را بر اساس فواصل تنفس كوتاهتري، بيشتر كرد. مثلا با اعداد پيش فرض سيستم، با فايل صوتي فوق به 5 خروجي خواهيد رسيد؛ اما با توجه به تنظيماتي كه در تصوير مشاهده مي‌كنيد، به 8 خروجي متعادل‌تر مي‌رسيم.


مزايا:
  • كار زمانبندي زير نويس خودكار مي‌شود.
  • تا حدود 60 درصد، خروجي متني مطمئني را مي‌توان شاهد بود.

در مورد ويندوز XP :

ويندوز XP به صورت پيش فرض داراي موتور Speech Recognition نيست. دو راه براي نصب آن در اين سيستم وجود دارد:

الف) استفاده از بسته نرم افزاري آفيس XP
به كنترل پنل مراجعه كرده، گزينه‌ي Add/remove programs را انتخاب نمائيد. در اينجا Microsoft Office XP را انتخاب و بر روي دكمه Change كليك كنيد. نياز است تا يكي از ويژگي‌هاي نصب نشده آن‌را نصب كنيم. به همين جهت در صفحه ظاهر شده، Add or Remove Features را انتخاب و در ادامه در قسمت Features to install ، گزينه‌ي Office Shared Features را انتخاب كنيد. ذيل مدخل Alternative User Input، امكان انتخاب و نصب Speech مهيا است.

ب) استفاده از Microsoft Speech SDK Setup 5.1
بر روي ويندوز 7، نگارش 8 اين برنامه نصب است؛ اما براي ويندوز XP تا نگارش 5.1 بيشتر ارائه نشده است. فايل‌هاي آن‌را از اينجا مي‌توانيد دريافت كنيد. نصب آن هم در اينجا توضيح داده شده.


من در كل ويندوز XP را براي اينكار توصيه نمي‌كنم چون هم موتور تشخيص صداي آن قديمي است و هم حالت Asynchronous آن درست كار نمي‌كند. براي مثال اين يك خروجي تهيه شده از همان فايل voice فوق، توسط موتور تشخيص صداي مخصوص ويندوز XP است كه بي‌شباهت به طنز نيست!


۱۳۹۰/۰۸/۰۳

آشنايي با BOM !


سؤال: دو فايل زيرنويس فارسي داريم، هر دو هم با فرمت UTF-8 ذخيره شده‌اند. يكي در دستگاه DVD Player درست نمايش داده مي‌شود و ديگري خير. چرا؟!
هر دو فايل را اگر در يك اديتور متني باز كنيم تفاوتي قابل مشاهده نيست؛ اما در يك Hex Editor خير:



در سه بايت اول فايل با هم تفاوت دارند و اصطلاحا به اين سه بايت BOM يا Byte order mark گفته مي‌شود. توسط آن مي‌توان تشخيص داد كه فايل جاري اولا آيا با فرمت يونيكد ذخيره شده است يا خير ثانيا كدام حالت به كار گرفته شده است؛ آيا UTF-8 است يا UTF-16 يا ...؟
در حالت UTF-8 مقدار BOM مساوي با 0xEF,0xBB,0xBF بوده و البته ذكر آن اختياري است. به نظر اين دستگاه DVD Player ياد شده، به اين نكته حساس است.
در دات نت جهت اطمينان از نوشته شدن BOM در فايل توليدي، نياز است encoding نهايي صريحا ذكر گردد. براي مثال هرچند خروجي File.WriteAllText حتي بدون ذكر encoding آن، UTF-8 است، اما BOM را به همراه ندارد (^). براي رفع اين مساله بايد از روش زير استفاده كرد:

File.WriteAllText(path, data, Encoding.UTF8);  


۱۳۹۰/۰۵/۱۳

تبديل زيرنويس‌هاي يوتيوب به فايل srt


تعدادي از ويديوهاي يوتيوب، خصوصا مواردي كه از Google videos به يوتيوب منتقل شده‌اند، داراي زير نويس هستند. اين زير نويس هم فرمت جالبي دارد:
<?xml version="1.0" encoding="UTF-8"?>
<transcript>
<text start="23.49" dur="5.97">
&amp;gt;&amp;gt;Commentator: We have here today, Steve with
us whom I met not too long ago at something
</text>
...
</transcript>
و از هر لحاظ بهتر است از فرمت srt متداول (خصوصا از لحاظ قابليت بهتر parse آن) ولي ... اين فرمت xml ايي، متداول نيست و بهتر است جهت استفاده از آن در برنامه‌هاي پخش كننده فايل‌هاي ويديويي، به srt تبديل شود.
ابتدا شايد بپرسيد كه اين‌ها را چگونه مي‌توان دريافت كرد. روش كار به صورت زير است:
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);
}
}
}


مطالب تكميلي:
همه چیز درباره زیرنویس ویدئوهای گوگل

۱۳۸۹/۰۹/۱۳

معرفي برنامه‌ي Subtitle Tools


اين روزها زيرنويس‌هاي فارسي فيلم‌هاي روز دنيا را راحت مي‌شود در اينترنت يافت، اما مشكلات زيادي هم به همراه اين نوع فايل‌ها وجود دارند:
- گاها با فيلم دريافت شده هماهنگ نيستند.
- عموما با فرمت windows-1256 تهيه مي‌شوند كه براي استفاده از آن‌ها در سيستم‌هاي مختلف بهتر است به UTF8 تبديل شوند.
- اكثر برنامه‌هاي موجود براي كار با زير نويس‌ها و ويرايش آن‌ها، دركي از يونيكد ندارند.
- عموما نياز است جهت استفاده از آن‌ها در يك جمع، تعدادي از سطور آن‌ها را با حفظ شماره بندي فايل، حذف كرد!
و ...

به همين جهت نياز به يك برنامه‌ي جمع و جور جهت كار با زير نويس‌ها داشتم كه نتيجه‌ي آن تهيه‌ي برنامه‌ي زير شد:

الف) تغيير encoding فايل دريافتي به UTF-8
هنگام گشودن اكثر فايل‌هاي زير نويس فارسي با تصوير زير روبرو خواهيد شد:



براي تبديل آن به فرمت يونيكد تنها كافي است بر روي دكمه‌ي To UTF-8 كليك كنيد. در اين حالت نتيجه به صورت زير خواهد بود:



ب) هماهنگ سازي زير نويس با فيلم دريافتي
ممكن است ديالوگ‌هاي زير نويس دريافتي شما به اندازه‌ي مدت زمان خاصي، از ديالوگ‌هاي فيلم در حال پخش، عقب‌تر يا جلوتر باشند. در اين حالت ابتدا بايد اين مدت زمان را با گوش فرا دادن به ابتداي فيلم و مقايسه‌ي آن با اولين شماره‌ي زيرنويس، پيدا كنيد. مثلا پس از بررسي متوجه شده‌ايد كه به كليه زمان‌هاي زيرنويس جاري بايد 7 ثانيه اضافه گردد. اينكار را مطابق تصوير ذيل مي‌توان انجام داد:



ج) يكي كردن زمان‌هاي دو زير نويس با هم
گاهي از اوقات مشكلات زماني يك زيرنويس وخيم‌تر از مورد ب است. به اين معنا كه شماره‌هاي مختلف آن، زمان‌هاي كاملا بي‌ربطي داشته و به صورت هماهنگ، قابل افزايش يا كاهش نيستند. در اين حالت ابتدا زير نويس مورد نظر را در برنامه باز كنيد. سپس يك زير نويس خوب انگليسي هماهنگ با فيلم را نيز پيدا كنيد و از طريق دكمه‌ي Merge times به برنامه معرفي نمائيد. در اين حالت به صورت خودكار زمان‌هاي صحيح از زير نويس دوم به زير نويس اول منتقل خواهند شد.

د) يكي كردن دو فايل زير نويس با هم
ممكن است فيلم دريافتي تنها از يك فايل تشكيل شده باشد، اما شما فقط توانسته‌ايد زير نويس مرتبط با نگارش دو سي دي اين فيلم را پيدا كنيد. بنابراين نياز است تا اين دو فايل زير نويس يكي شوند با اين شرط كه زمان‌هاي سي دي دوم از انتهاي سي دي اول در فايل نهايي يكي شده‌ي توليدي شروع گردد.
براي اين منظور ابتدا فايل زيرنويس سي دي اول را در برنامه باز كرده و سپس به گزينه‌ي join files در برنامه مراجعه كنيد. در اينجا ابتدا مسير فايل زيرنويس سي دي 2 را مشخص نمائيد. برنامه سعي خواهد كرد تا زمان آغاز قسمت دوم را بر اساس آخرين زمان سي دي اول و اولين زمان سي دي دوم حدس بزند و نمايش دهد. يا مي‌توانيد اين مقدار پيش فرض را پذيرفته و بر روي دكمه‌ي join كليك نمائيد و يا امكان تغيير دستي آن هم ميسر است.



ه) حذف و يا ويرايش رديف‌ها
به دلايل نامشخصي اشخاصي كه سعي در ترجمه‌ي زيرنويس‌ها مي‌كنند عموما علاقمندند كه به متن اصلي وفادار بمانند. به همين دليل نياز به جرح و تعديل زيرنويس‌هاي تهيه شده براي نمايش در يك جمع خانوادگي وجود دارد. گزينه‌ي جستجوي موجود در بالاي رديف‌هاي زيرنويس باز شده در برنامه، امكان نمايش رديف‌هايي را كه حاوي متن وارد شده است، به صورت خودكار دارد.



در اين حالت اگر نياز است سطري حذف شود، آن‌را انتخاب نموده و بر روي دكمه‌ي Delete row كليك نمائيد. در اين حالت علاوه بر حذف رديف، كليه شماره‌هاي موجود در زير نويس نيز به صورت خودكار مجددا توليد و مرتب خواهند شد. (كليك راست بر روي هر رديف نيز اين گزينه‌ را نمايش مي‌دهد)
يا اگر مشغول به ويرايش متني شديد، پس از ويرايش، كليك كردن بر روي دكمه‌ي Save را فراموش نكنيد (در حالت حذف نيازي به اينكار نيست).

ز) پيدا كردن زيرنويس يك فايل بر اساس امضاي ديجيتال آن
سايت opensubtitles.org يك API را جهت پيدا كردن زيرنويسي مطابق با هش يك فايل ويديويي ارائه داده است، كه در برنامه‌ي جاري، كلاينتي براي آن تهيه شده است:



فقط كافي است فايل ويديويي خود را در اين قسمت انتخاب نمائيد. برنامه هش فايل را محاسبه كرده و سپس با كمك سرويس XML-RPC سايت opensubtitles.org سعي در يافتن زيرنويس هماهنگ با آن خواهد كرد. در اينجا ديگر مهم نيست نام فايل انتخابي چيست؛ امضاي ديجيتال آن مهم است. براي دريافت موارد مورد نظر، ابتدا آن‌ها را تيك زده و سپس بر روي دكمه‌ي دريافت كليك كنيد. كليك راست بر روي رديف مورد نظر نيز اين امكان دريافت را لحاظ كرده است.
همچنين قسمتي هم براي آپلود زيرنويس به اين سايت پيش بيني شده است (لطفا مصرف كننده‌ي صرف يا به قولي ليچر نباشيد!)



در اينجا انتخاب فايل ويديويي، فايل زيرنويس هماهنگ با آن و همچنين زبان زير نويس الزامي است. از فايل ويديويي جهت محاسبه‌ي هش آن براي يافتن ساده‌تر زيرنويس‌ها در دفعات آتي استفاده مي‌گردد.

پيشنياز استفاده از اين برنامه، نصب دات نت فريم ورك 4 است كه اگر از ويندوز 7 استفاده مي‌كنيد، جزو به روز رساني‌هاي اختياري آن است و در حالت كلي نسخه‌ي كامل 32 بيتي و 64 بيتي آن از اين آدرس قابل دريافت است.