اصلاح انکودینگ زیرنویس SRT بدون از دست رفتن متن اصلی
عیبیابی متنهای بههمریخته در SRT، تشخیص خطاهای رمزگشایی از کاراکترهای حذفشده، و ایجاد یک نسخه مجزای UTF-8 با ابزار امن پایتون و نمونههای قابل تکرار.

اگر زیرنویس SRT شما به جای café عبارت caféرا نشان میدهد، بلافاصله فایل را با فرمت UTF-8 ذخیره نکنید. ابتدا یک نسخه دستنخورده از بایتهای آن نگه دارید، انکودینگی را پیدا کنید که کلمات درست را تولید میکند، و سپس متن تأییدشده را در یک فایل جداگانه ذخیره کنید. ذخیره کردن کاراکترهای اشتباه با یک انکودینگ جدید، فقط همان اشتباهات را تثبیت میکند.
نکته کلیدی، تفاوت میان انکودینگ معتبر و متن صحیحاست. در آزمایش نمونه دو خطی زیر، یکی از فایلهای خراب تمام بررسیهای سختگیرانه UTF-8 را با موفقیت پشت سر میگذارد و هیچ کاراکتر جایگزینی هم ندارد، اما متن فرانسوی آن همچنان اشتباه است. فایل دیگر نیز همین بررسی را پس از جایگزین شدن شش کاراکتر اصلی با �.
این راهنما شامل یک ابزار محلی پایتون برای بررسی و تبدیل، فایلهای منبع قابل دانلود، و یک تست با قابلیت بازتولید است. این ابزار به تشخیص در سطح فایل و تبدیل صریح میپردازد—نه تشخیص خودکار انکودینگ، هماهنگسازی ویدیو یا وعدهای برای بازیابی حروف حذفشده.
ابتدا مشخص کنید دقیقا چه چیزی خراب است
پسوند .srt فقط نشاندهنده فرمت زیرنویس است، نه تضمینی برای یک انکودینگ خاص. فرمت SRT شامل شماره خطوط، زمانبندیها، متن و جداکنندهها است؛ و سند مشخصات فرمت SRT در کتابخانه کنگره، آن را متنی ساده و بدون یک استاندارد واحد برای انکودینگ کاراکترها توصیف میکند.
مشکل ظاهری را به عنوان دلیلی برای بررسی بیشتر در نظر بگیرید، نه خودِ تشخیص نهایی:
| آنچه میبینید | آنچه باید بررسی شود | اقدام بعدی مناسب |
|---|---|---|
| اعرابها، علائم یا نمادها در یک برنامه اشتباه نمایش داده میشوند | آیا باز کردن مجدد فایل دستنخورده با انکودینگ مبدأِ مشخص، متن صحیح را نمایش میدهد؟ | اگر بله، پیش از گرفتن خروجی جدید، از همان رمزگشایی صریح استفاده کنید. |
café در فایلی که به درستی با انکودینگ UTF-8 خوانده شده همچنان باقی میماند | آیا UTF-8 قبلاً بهاشتباه با کدبندی دیگری خوانده و ذخیره شده است؟ | به بایتهای اصلی بازگردید یا تاریخچهٔ دقیق تبدیل را بررسی کنید. ذخیرهٔ مجدد با UTF-8 کارساز نیست و فایل را ترمیم نمیکند. |
� به جای یک حرف یا نماد نمایش داده میشود | آیا نویسهٔ U+FFFD واقعاً درون فایل ذخیره شده است، یا برنامهٔ فعلی هنگام نمایش بایتهای غیرقابلرمزگشایی آن را درج میکند؟ | فایل منبعِ دستنخورده را بررسی کنید. نویسهٔ جایگزینی که در فایل ذخیره شده باشد، نویسهٔ اصلی را مشخص نمیکند. |
| در پلیر مربعهای توخالی دیده میشود، اما یک ویرایشگر متنِ مطمئن نویسههای درست را نشان میدهد | آیا نقاط کد زیربنایی درست هستند؟ آیا پلیر دقیقاً همان فایل را بارگذاری میکند؟ | پیش از تغییر دادن فایل، نحوهٔ رمزگشایی پلیر، پوشش فونت یا تنظیمات رندرینگ آن را بررسی کنید. |
نویسهها با شکل نمایشی آنها تفاوت دارند. مستندات توضیح یونیکد در پایتون، نقاط کد را از گلیفهای رندرشده توسط فونت متمایز میکند. درست بودن متن در ویرایشگر نشان میدهد که احتمالاً مشکل از سمت پلیر است؛ اما ثابت نمیکند که نصب یک فونت خاص حتماً آن را حل خواهد کرد. برای این مقاله هیچ فونت یا پلیری تست نشده است.
پشتیبانگیری از بایتها و سپس بررسی یک رمزگشایی
فایل subtitle_encoding.py را دانلود کرده و کنار فایل SRT مورد نظرتان قرار دهید. اجرای این دستورها نیازمند نصب بودن پایتون ۳ است و به هیچ بستهٔ اضافی نیاز ندارد. بررسیهای محلی در اینجا با پایتون 3.14.3 روی macOS انجام شده است. اگر در ویندوز از Python launcher استفاده میکنید، py -3 را جایگزین python3کنید؛ آن محیط در اینجا تست نشده است.
ترمینال را در همان پوشه باز کنید. در این مثالها، input.srt را با نام واقعی فایل خود جایگزین کنید. اگر مسیر فایل دارای فاصله است، از علامت نقلقول در دو طرف آن استفاده کنید.
تهیهٔ یک نسخهٔ کپی دستنخورده
python3 subtitle_encoding.py backup "input.srt" "original-bytes.srt"
مسیر مقصد نباید از قبل وجود داشته باشد. این ابزار بایتها را بدون رمزگشایی کپی میکند، فایل کپیشده را بازخوانی کرده و هش SHA-256 آن را گزارش میدهد. همچنین اجازه نمیدهد مسیر مبدأ بهعنوان مقصد تعیین شود. این نسخهٔ پشتیبان را حتی پس از ساخت زیرنویس قابلاستفاده نیز نگه دارید.
بررسی UTF-8 بدون ذخیرهٔ هیچ تغییری
python3 subtitle_encoding.py inspect "original-bytes.srt"
این گزارش شامل strict_utf8, utf8_bom، کدبندی انتخابشده و — در صورت موفقیتآمیز بودن رمزگشایی — پیشنمایشی از متن و replacement_characters را گزارش میدهد. نمای متنی پیشفرض آن از utf-8-sigاستفاده میکند که امضای ابتدایی UTF-8 را مدیریت مینماید.
strict_utf8: falseبه این معنی است که بایتها در بررسی UTF-8 رد شدهاند؛ این موضوع به شما نمیگوید که کدام انکودینگ دیگر درست است.strict_utf8: trueیعنی آنها را میتوان بهصورت UTF-8 رمزگشایی کرد؛ اما این لزوماً به این معنی نیست که کلمات صحیح هستند.- تعداد جایگزینی غیرصفر به این معنی است که رمزگشایی انتخابی باعث ایجاد کاراکترهای U+FFFD شده است. پیش از ایجاد فایل جدید، آنها را بررسی کنید.
بازرسی، خروجی JSON سازگار با ASCII چاپ میکند تا فونت ترمینال نتواند هویت کاراکتر را پنهان کند: \u00e9 به معنای é، و \ufffd به معنای کاراکتر جایگزین است. برای بررسی دقیق یک سطر مشکوک، شماره سطر فیزیکی آن را بخواهید—نه شماره کیو (cue) زیرنویس را:
python3 subtitle_encoding.py inspect "original-bytes.srt" --encoding cp1252 --line 3
این یک آزمایش فقط-خواندنی برای Windows-1252، یعنی کدک cp1252 در پایتون است. زمانی از آن استفاده کنید که تنظیمات خروجیگرفتن یا پیشینه فایل مبدأ این انتخاب را تأیید کند، نه فقط به این دلیل که این مثال تصادفاً فرانسوی بوده است. گزارش سطر، نام هر کاراکتر و کدپوینت آن را نشان میدهد؛ U+20AC همان نماد یورو است.
انکودینگ را بر اساس شواهد انتخاب کنید، نه اولین پیشنمایش موفق
انکودینگ واقعی فایل خروجی را از سازنده آن جویا شوید، تنظیمات برنامه صادرکننده را بررسی کنید، یا آن را با متن اصلی و قابلاعتماد مقایسه نمایید. نامهای دارای اعراب، علائم نگارشی، نمادهای ارز و سطرهای شاخص را در سرتاسر فایل مرور کنید. اگر به آن زبان مسلط نیستید، یک رمزگشایی موفق نمیتواند این بررسی را بهجای شما انجام دهد.
عنوان «ANSI» برای انتخاب کدک مبدأ به اندازه کافی دقیق نیست. همچنین Windows-1252 و Latin-1 نیز قابل جایگزینی با یکدیگر نیستند. در آزمایش ارائهشده، تکبایت 80 تحت انکودینگ € به cp1252رمزگشایی میشود، اما در Latin-1 به کاراکتر کنترلی U+0080 تحت latin-1تبدیل میشود. هر دو عملیات با موفقیت انجام میشوند؛ تنها دانستن منبع اصلی مشخص میکند کدام مورد مد نظر بوده است.
سایر زبانها ممکن است از انکودینگهای قدیمی متفاوتی استفاده کنند، اما صرفاً نام یک زبان نمیتواند انکودینگ را تعیین کند. اگر پیشینه فایل مشخص نیست و خوانشهای احتمالی با هم همخوانی ندارند، پیش از تبدیل دست نگهدارید و شواهد بهتری درباره منبع به دست آورید.
تبدیل را فقط پس از خوانا شدن متن منبع انجام دهید
برای فایلی که تأیید شده است از نوع Windows-1252 است، یک فایل مجزای UTF-8 بسازید:
python3 subtitle_encoding.py convert "original-bytes.srt" "repaired-utf8.srt" --from-encoding cp1252
python3 subtitle_encoding.py inspect "repaired-utf8.srt"
مبدل کل فایل منبع را بهصورت دقیق (strict) رمزگشایی میکند، آن متن را با فرمت UTF-8 انکود مینماید، بررسی میکند که رمزگشایی خروجی دقیقاً همان متن را برگرداند، و بایتهای نوشتهشده را بازخوانی میکند. این ابزار شماره کیوها، تایماستمپها، دیالوگها، تگها یا پایان خطوط را ویرایش نمیکند. توالی بایتهای جدید ممکن است متفاوت باشد، حتی اگر متن رمزگشاییشده کاملاً یکسان بماند.
این ابزار عمداً از انجام موارد زیر خودداری میکند:
- بازنویسی روی فایل مقصدی که از قبل وجود دارد؛
- ادامه دادن فرایند پس از بروز خطای رمزگشایی سختگیرانه (strict)؛ یا
- نوشتن متنی که شامل U+FFFD باشد، حتی اگر آن نویسه از روی قصد قرار داده شده باشد.
محدودیت آخر کاملاً محتاطانه در نظر گرفته شده است: این ابزار نمیتواند تشخیص دهد که یک نویسه جایگزین نماینده چه چیزی بوده است. حذف آن برای اجرا شدن دستور، شواهد را از بین میبرد و متن را بازیابی نمیکند. بخش مستندات مدیریت خطای پایتون توضیح میدهد که چرا replace و ignore با رمزگشایی دقیق متفاوت هستند: آنها دادههای مشکلدار را جایگزین یا حذف میکنند. هیچکدام از این دو روش جایی در این مرحله از تبدیل ندارند.
اگر خطای I/O رخ داد، از خروجی ناقص استفاده نکنید. ممکن است یک فایل جدید و نیمهکاره باقی بماند؛ فایل اصلی را نگه دارید و برای تلاش بعدی از نام مقصد جدیدی استفاده کنید. رفتار کامل ابزار و نحوه استفاده از آن در فایل README قابل دانلود.
درباره UTF-8 همراه با BOM چطور؟
شاخص UTF-8 BOM توالی بایت ابتداییِ EF BB BFاست. کدکِ utf-8-sig پایتون این امضا را هنگام رمزگشایی مصرف کرده و هنگام انکود کردن به فایل اضافه میکند.
برای یک منبع تأییدشده UTF-8 به همراه BOM، از --from-encoding utf-8-sigاستفاده کنید. این ابزار معمولاً UTF-8 را بدون BOM مینویسد؛ تنها زمانی --with-bom را اضافه کنید که الزامات برنامه مقصد آن را ایجاب کند. تغییر دادن BOM نمیتواند café را به caféتبدیل کند. این آزمایش سازگاری با هیچ پخشکننده، ویرایشگر یا پلتفرم بارگذاری خاصی را تضمین نمیکند.
پنج فایل کوچک نشان میدهند که چرا معتبر بودن UTF-8 بهتنهایی کافی نیست
این آزمایش از دو بخش زیرنویس فرانسوی که کاملاً توسط نویسنده تألیف شدهاند استفاده میکند. اینها از فیلم، مشتری یا محصول ترجمهای گرفته نشدهاند:
1
00:00:01,000 --> 00:00:04,000
Émile dit : « Le prix est de 12,50 €. »
2
00:00:05,000 --> 00:00:08,000
Le café est fermé.
در تاریخ ۱۳ سپتامبر ۲۰۲۶، یک اسکریپت با کتابخانه استاندارد پایتون ۳.۱۴.۳ پنج نمایش بایتی ایجاد کرد و هر کدام را با آن منبع مشخص مقایسه نمود. اینها بررسیهای قطعی بایت و رشته متنی هستند، نه معیاری برای سنجش کیفیت ترجمه. فایلهای پیوستشده را به جای کپی کردن پیشنمایش مرورگر در دیسک ذخیره کنید: بایتهای متفاوت اصل این آزمایش هستند.
| نسخه قابل دانلود | بایتها | UTF-8 دقیق و معتبر؟ | آیا متن پس از رمزگشایی به صورت UTF-8 صحیح است؟ | کاراکتر U+FFFD ذخیرهشده در متن UTF-8 آن |
|---|---|---|---|---|
| UTF-8 اصلی | 132 | بله | بله | 0 |
| Windows-1252 اصلی | 125 | خیر | به عنوان UTF-8 قابل رمزگشایی نیست؛ صحیح تحت cp1252 | نامربوط |
| رمزگشایی نادرست، بازذخیرهشده به عنوان UTF-8 | 147 | بله | خیر | 0 |
| کاراکترهای جایگزین، بازذخیرهشده به عنوان UTF-8 | 137 | بله | خیر | 6 |
| UTF-8 با تبدیل صحیح | 132 | بله | بله | 0 |
هر نسخه همان دو رشته برچسب زمانی را حفظ میکند. فایل بهدرستی تبدیلشده، بایتبهبایت با نسخه اصلی UTF-8 یکسان است. دو فایل آسیبدیده UTF-8 نکتهای محدودتر اما کاربردی را اثبات میکنند: نه انکودینگ معتبر و نه برچسبهای زمانی تغییرنیافته، هیچکدام صحت متن زیرنویس را تضمین نمیکنند. همچنین تطابق برچسبهای زمانی هیچ نشانهای از هماهنگی این زیرنویس ساختگی با یک ویدیوی واقعی ارائه نمیدهد.
برای بازتولید این پنج فایل توسط خودتان، فایل reproduce.py را دانلود کرده و آن را با نام پوشهای که وجود ندارد اجرا کنید:
python3 reproduce.py encoding-experiment
این اسکریپت فایلهای نمونه و یک results.json شامل متن کامل، تبدیلات، هشها، نسخه محیط اجرا و اعتبارسنجیها ایجاد میکند. آن را با نتایج ثبتشده آزمایشمقایسه کنید؛ برچسب زمانی ایجاد متفاوت خواهد بود. اسکریپتها و فایلهای آموزشی اولیه شامل یک مجوز MIT.
بررسیهای مبدل محلی مواردی مانند خودداری از بازنویسی فایل خروجی موجود، خودداری از پذیرش مسیر منبع، خطا در صورت کدک نادرست، نپذیرفتن U+FFFD، حفظ ساختار خطوط CRLF و تولید صریح BOM را نیز آزمایش کردند. این بررسیها رفتار فایل این ابزار را تایید میکنند. آنها نحوه نمایش در پخشکننده، هماهنگی زمانی با رسانه واقعی یا ترجمه BookTranslator را بررسی نمیکنند.
اگر نویسههای خراب قبلاً ذخیره شده باشند
موجیباکه ذخیرهشده: بررسی دقیق سابقه تغییرات
نسخه موجیباکه ما از یک زنجیره مشخص پیروی کرد: بایتهای اصلی UTF-8 با انکودینگ Windows-1252 رمزگشایی شدند، سپس همان نویسههای اشتباه در قالب UTF-8 ذخیره شدند. نتیجه شامل café و دنباله نامعتبر یورو €.
از آنجا که در این تبدیل ویژه هیچ بایتی از دست نرفته است، اسکریپت بازتولید میتواند آن را معکوس کند: انکود مجدد متن اشتباه از طریق cp1252و سپس رمزگشایی بایتهای حاصل در قالب UTF-8. این اسکریپت متن بازیابیشده را با نسخه اصلی مطابقت میدهد.
این مدرکی است برای این زنجیره شناختهشده، نه دستوری برای اعمال یک عملیات فراگیر «ترمیم موجیباکه» روی تمامی فایلهای SRT. یک فایل ممکن است حاوی نویسههای معتبر، سوابق ترکیبی یا متنی باشد که قبلاً طی یک تلاش برای ترمیم تغییر کرده است. اولویت با فایل منبع دستنخورده و مسیر استاندارد تبدیل است. اگر تنها موجیباکه ذخیرهشده باقی مانده است، آن را نگه دارید و پیش از تلاش برای اعمال تبدیل معکوس روی یک نسخه کپی دیگر، نحوه ایجاد آن را دقیقاً مشخص کنید.
نویسههای جایگزین ذخیرهشده: حرفِ حذفشده اصلاً در آنجا کدگذاری نشده است
نمونه فایل آسیبدیده با رمزگشایی بایتهای Windows-1252 بهصورت UTF-8 با فعال بودن جایگزینی و سپس ذخیره نتیجه ایجاد شده است. نویسههای اصلی متفاوتی همگی به نشانگر یکسانِ � تبدیل شدهاند. نشانگر ذخیرهشده اطلاعات کافی برای تشخیص اینکه کدام نویسه اصلی در آن جایگاه قرار داشته را در خود ندارد.
این موضوع را با صرفاً مشاهده کردنِ � آن در یک برنامه اشتباه نگیرید. اگر بایتهای اصلی دستنخورده باقی مانده باشند، یک رمزگشایی صحیح همچنان میتواند متن را بازیابی کند—همانطور که برای منبع Windows-1252 ما عمل میکند. قبل از اعلام قطعی از دست رفتن دادهها، فایل منبع را بررسی کنید.
اگر تنها نسخه باقیمانده واقعاً متن مفقود را با U+FFFD یا علامتهای سؤال واقعی جایگزین کرده باشد، فایل را دوباره خروجی بگیرید یا یک منبع دستنخورده تهیه کنید، یا بازنویسی دستی را با منبعی معتبر تطبیق دهید. یک علامت سؤال معمولی میتواند صرفاً یک علامت نگارشی مجاز هم باشد؛ صرفِ وجود آن دلیلی بر خرابی نیست. حدس محتمل یک مدل هوش مصنوعی فقط یک حدس است، نه دادههای بازیابیشده فایل.
هدف، دستیابی به یک منبع خواناست—نه فقط اجرای موفق یک دستور
پیش از تأیید نهایی فایل اصلاحشده، کلمات و نمادهای شاخص را با منبع معتبر مقایسه کنید، مطمئن شوید خطوط شمارهگذاری و برچسبهای زمانی تغییر نکردهاند و فایل جدید را در برنامهای که قرار است از آن استفاده کند باز کنید. این اسکریپت متن رمزگشاییشده را حفظ میکند؛ اما اعتبارسنج ساختار SRT یا آزمون نهایی پخش ویدیو نیست.
اگر اکنون میتوانید زیرنویس را بخوانید و به زبان دیگری نیاز ندارید، کار تمام است. اگر نیاز به بازبینی همزمان با ویدیو یا ویرایشهای بیشتر دارید، مقایسه نرمافزارهای زیرنویس نقش و کاربرد ابزارهای مختلف را توضیح میدهد.
تنها زمانی که از درستی متن مبدأ اطمینان یافتید—و واقعاً به زبان دیگری نیاز داشتید—به سراغ مترجم زیرنویس BookTranslator و گردش کار ترجمه زیرنویس با هوش مصنوعیبروید. اصلاح انکودینگ، ترجمه، و بازبینی نهایی ویدیو را به عنوان مراحل جداگانه در نظر بگیرید. موفقیت در یکی از آنها، لزوماً به معنای موفقیت در مراحل دیگر نیست.
مطالب مرتبط





