最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Python代碼實(shí)現(xiàn)將USF字幕格式轉(zhuǎn)換為SRT

 更新時間:2026年03月04日 09:16:42   作者:林九生  
在影音處理、字幕整理、視頻本地化等場景中,我們經(jīng)常會遇到不同字幕格式需要互轉(zhuǎn)的情況,其中USF是一種基于 XML 的字幕格式,下面我們就來看看具體實(shí)現(xiàn)方法吧

字幕處理:USF 字幕格式轉(zhuǎn)換為 SRT

在影音處理、字幕整理、視頻本地化等場景中,我們經(jīng)常會遇到不同字幕格式需要互轉(zhuǎn)的情況,其中 USF(Universal Subtitle Format) 是一種基于 XML 的字幕格式,而 SRT(SubRip Subtitle)則是最常見、最被播放器和編輯軟件支持的格式。

本文分享一段 實(shí)戰(zhàn) Python 代碼,完成 USF → SRT 轉(zhuǎn)換,并對處理流程、注意事項、關(guān)鍵邏輯逐行解析,開箱即用。

USF 與 SRT 有什么區(qū)別

特性USFSRT
結(jié)構(gòu)基于 XML文本文件
時間格式HH:MM:SS.sssHH:MM:SS,mmm
支持樣式字體、大小、顏色等豐富信息純文本(基礎(chǔ)格式)
主流播放器支持較少廣泛支持

因此,當(dāng)我們從專業(yè)字幕制作工具導(dǎo)出 USF 后,轉(zhuǎn) SRT 才能在視頻播放器、剪輯軟件、硬字幕工具中正常使用。

本文解決的核心問題

解析 USF 字幕

將時間轉(zhuǎn)換為 SRT 格式

處理跨天字幕(24:00→00:00 的情況)

處理多 text 節(jié)點(diǎn)合并

確保字幕序號、文本、時長合法

一行代碼調(diào)用完成轉(zhuǎn)換

完整 Python 代碼(USF → SRT)

import re
from pathlib import Path
import xml.etree.ElementTree as ET


def parse_hms_to_seconds(time_str: str) -> float:
    m = re.match(r"^(\d{2}):(\d{2}):(\d{2})(?:\.(\d{1,3}))?$", time_str.strip())
    if not m:
        raise ValueError(f"Invalid time format: {time_str}")
    h, mi, s, ms = m.groups()
    hours = int(h)
    minutes = int(mi)
    seconds = int(s)
    millis = int(ms) if ms is not None else 0
    return hours * 3600 + minutes * 60 + seconds + millis / 1000.0


def format_seconds_to_srt(total_seconds: float) -> str:
    total_ms = int(round(total_seconds * 1000))
    hours = total_ms // 3_600_000
    rem = total_ms % 3_600_000
    minutes = rem // 60_000
    rem = rem % 60_000
    seconds = rem // 1000
    millis = rem % 1000
    return f"{hours:02d}:{minutes:02d}:{seconds:02d},{millis:03d}"


def clean_text(text: str) -> str:
    t = text.replace("\r\n", "\n").replace("\r", "\n")
    t = re.sub(r"\n{3,}", "\n\n", t)
    return t.strip()


def convert_usf_to_srt(usf_path: Path, srt_path: Path | None = None) -> Path:
    if srt_path is None:
        srt_path = usf_path.with_suffix(".srt")

    tree = ET.parse(usf_path)
    root = tree.getroot()

    subs_root = root.find(".//subtitles")
    if subs_root is None:
        raise ValueError("USF file missing <subtitles> section")

    items = []
    day_offset = 0
    prev_base_start = None

    for sub in subs_root.findall("subtitle"):
        start_attr = sub.get("start")
        stop_attr = sub.get("stop")
        if not start_attr or not stop_attr:
            continue

        base_start = parse_hms_to_seconds(start_attr)
        base_stop = parse_hms_to_seconds(stop_attr)

        if prev_base_start is not None and base_start < prev_base_start:
            day_offset += 1

        start_seconds = base_start + day_offset * 86400
        stop_seconds = base_stop + day_offset * 86400
        if base_stop < base_start:
            stop_seconds += 86400

        texts = []
        for tnode in sub.findall("text"):
            content = "".join(tnode.itertext())
            if content:
                texts.append(clean_text(content))
        text_joined = "\n".join([t for t in texts if t])
        if not text_joined:
            text_joined = ""

        items.append((start_seconds, stop_seconds, text_joined))
        prev_base_start = base_start

    lines = []
    for idx, (st, en, txt) in enumerate(items, start=1):
        start_str = format_seconds_to_srt(st)
        end_str = format_seconds_to_srt(en)
        lines.append(str(idx))
        lines.append(f"{start_str} --> {end_str}")
        lines.append(txt)
        lines.append("")

    srt_path.write_text("\n".join(lines), encoding="utf-8")
    return srt_path


def main():
    usf_file = Path(r"20251120.usf")
    out_file = Path(r"20251120.srt")
    srt_path = convert_usf_to_srt(usf_file, out_file)
    print(f"SRT written: {srt_path}")


if __name__ == "__main__":
    main()

核心邏輯解析

USF 時間解析(帶毫秒)

USF 中時間格式為:

HH:MM:SS.sss

使用正則解析并轉(zhuǎn)換為秒:

parse_hms_to_seconds()

例如:

00:03:12.500 → 192.5 秒

防止跨天錯誤

有些字幕可能這樣:

startstop
123:59:5523:59:58
200:00:0200:00:06

看起來像倒退了,其實(shí)是跨天。

代碼自動維護(hù) day_offset,避免:

00:00:02 比 23:59:55 更早

合并多段文本內(nèi)容

USF 一個 subtitle 下可能有多個 <text>,例如:

<subtitle start="00:03:00" stop="00:03:05">
    <text>第一行</text>
    <text>第二行</text>
</subtitle>

輸出自動:

第一行
第二行

SRT 輸出格式

符合標(biāo)準(zhǔn):

序號
HH:MM:SS,mmm --> HH:MM:SS,mmm
字幕內(nèi)容

如何使用?

1.將 .usf 放到腳本所在目錄

2.修改:

usf_file = Path("example.usf")

3.運(yùn)行:

python convert.py

生成:

example.srt

播放器、硬字幕工具立即可用。

到此這篇關(guān)于Python代碼實(shí)現(xiàn)將USF字幕格式轉(zhuǎn)換為SRT的文章就介紹到這了,更多相關(guān)Python USF字幕轉(zhuǎn)SRT內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • PyTorch中torch.argmax函數(shù)的使用

    PyTorch中torch.argmax函數(shù)的使用

    torch.argmax 是一個高效的工具,廣泛應(yīng)用于分類模型預(yù)測、指標(biāo)計算等場景,下面就來介紹一下PyTorch中torch.argmax函數(shù)的使用,感興趣的可以了解一下
    2025-05-05
  • python使用writerows寫csv文件產(chǎn)生多余空行的處理方法

    python使用writerows寫csv文件產(chǎn)生多余空行的處理方法

    這篇文章主要介紹了python使用writerows寫csv文件產(chǎn)生多余空行的處理方法,需要的朋友可以參考下
    2019-08-08
  • Python3 數(shù)據(jù)結(jié)構(gòu)示例詳解

    Python3 數(shù)據(jù)結(jié)構(gòu)示例詳解

    本文介紹了Python中的四種基本數(shù)據(jù)結(jié)構(gòu)——列表、元組、集合和字典,以及如何根據(jù)具體需求選擇合適的數(shù)據(jù)結(jié)構(gòu),文章還展示了如何使用這些數(shù)據(jù)結(jié)構(gòu)進(jìn)行基本操作,并提供了示例代碼,感興趣的朋友跟隨小編一起看看吧
    2025-11-11
  • python中startswith()和endswith()的用法詳解

    python中startswith()和endswith()的用法詳解

    Python startswith() 方法用于檢查字符串是否是以指定子字符串開頭,endswith()方法主要是用于判斷字符串是否以指定字符或子字符串結(jié)尾,常用于判斷文件類型,對python startswith()和endswith()用法相關(guān)知識感興趣的朋友一起看看吧
    2021-10-10
  • Python?IDLE設(shè)置清屏快捷鍵的方法詳解

    Python?IDLE設(shè)置清屏快捷鍵的方法詳解

    這篇文章主要為大家詳細(xì)介紹了Python?IDLE設(shè)置清屏快捷鍵的方法,文中的示例代碼講解詳細(xì),具有一定的借鑒價值,感興趣的可以了解一下
    2022-09-09
  • pytorch中的自定義數(shù)據(jù)處理詳解

    pytorch中的自定義數(shù)據(jù)處理詳解

    今天小編就為大家分享一篇pytorch中的自定義數(shù)據(jù)處理詳解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-01-01
  • flask中獲取各種請求數(shù)據(jù)的常見方法小結(jié)

    flask中獲取各種請求數(shù)據(jù)的常見方法小結(jié)

    在 Flask 里,能使用多種方法獲取不同類型的請求數(shù)據(jù),這篇文章為大家詳細(xì)介紹了Flask中常見請求數(shù)據(jù)的獲取方式,有需要的小伙伴可以參考一下
    2025-06-06
  • Python讀取csv、Excel文件生成圖表的方法

    Python讀取csv、Excel文件生成圖表的方法

    這篇文章主要介紹了Python讀取csv、Excel文件生成圖表,本文通過示例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-07-07
  • 利用scrapy將爬到的數(shù)據(jù)保存到mysql(防止重復(fù))

    利用scrapy將爬到的數(shù)據(jù)保存到mysql(防止重復(fù))

    這篇文章主要給大家介紹了關(guān)于利用scrapy將爬到的數(shù)據(jù)保存到mysql(防止重復(fù))的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起看看吧。
    2018-03-03
  • PyTorch一小時掌握之圖像識別實(shí)戰(zhàn)篇

    PyTorch一小時掌握之圖像識別實(shí)戰(zhàn)篇

    這篇文章主要介紹了PyTorch一小時掌握之圖像識別實(shí)戰(zhàn)篇,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-09-09

最新評論

永善县| 赞皇县| 枣强县| 华阴市| 上蔡县| 阆中市| 从江县| 若羌县| 贵南县| 泰州市| 景德镇市| 楚雄市| 全州县| 晋宁县| 潞西市| 柳江县| 莆田市| 贵州省| 沾化县| 德清县| 望奎县| 吉木乃县| 藁城市| 绿春县| 景德镇市| 古田县| 遂昌县| 鄯善县| 凤山县| 瓦房店市| 清水县| 淮阳县| 南和县| 山丹县| 黎川县| 抚宁县| 鄄城县| 昌宁县| 德惠市| 黄石市| 临泽县|