<Python>将txt文本转为SRT格式字幕

前言
本例使用python来制作一个字幕生成器,主要有2种格式,分别是srt和ass。

环境配置:
平台:windows
工具:visual studiocode
语言:python
库:pyqt5

界面:

如上图,界面很简单,以实现功能为主,即导入txt文本,或者在左侧的文本框手动输入字幕文本,然后选择格式,最后点击“生成”,即可在右侧文本框内生成相应字幕格式的内容,点击“保存”即可将当前格式内容保存为本地文档。

下面介绍一下功能实现,主要讲一下两种格式的字幕内容如何生成。

1、srt格式

srt是最简单的一种字幕格式,它大致如下:

1

00:00:01,000 --> 00:00:02,000 你好

2

00:00:03,000 --> 00:00:04,000 这里是关于字幕格式转换的程序

3

00:00:05,000 --> 00:00:06,000 我们会将纯文本的文件

如上,srt文件的内容格式是一个索引,一个时间戳,对应一个文本,也就是一句字幕。
所以,如果用函数将纯文本撰文srt,大致逻辑如下:
读取文本内容,通常是一行一行的,我们对每一行文本添加时间戳和一个索引,在通用函数中,时间戳可以自动生成,不用管时间戳是否合适,后续可以手动调整。最后再将每行修改过的内容重新添加到一起,保存为srt格式的文件即可。
txttosrt代码:

 def txt_to_srt(self,txtcontent,start_time="00:00:00,000",interval=1000): 
        """文本转srt"""
        lines=txtcontent.split('\n')
        srt_lines = []  
        current_time = start_time  
        for index,line in enumerate(lines,start=1):
            line=line.strip()
            end_time=self.generate_timestamp_srt(current_time,interval)
            if line:
                timestamptext=f"{ current_time} --> { end_time}\n"
                timestamptext_html= f" { timestamptext}"  # 使用HTML标签包裹时间戳 
                srt_lines.append(f"{ index}\n")
                srt_lines.append(timestamptext_html)
                srt_lines.append(line+'\n')
                current_time=self.generate_timestamp_srt(end_time,interval)
        return srt_lines

其中涉及的时间戳生成函数generate_timestamp_srt如下:

 def generate_timestamp_srt(self,starttime,interval):
        """生成时间戳srt格式"""
        timeformat="%02d:%02d:%02d,%03d" 
        time=starttime.replace(",",":")
        hours, minutes, seconds, milliseconds = map(int, time.split(":"))  
        milliseconds += interval  
        seconds += milliseconds // 1000  
        milliseconds %= 1000  
        minutes += seconds // 60  
        seconds %= 60  
        hours += minutes // 60  
        minutes %= 60  
        return timeformat % (hours, minutes, seconds, milliseconds) 
2、ass格式

ass格式是比较复杂的一种字幕格式,因为这种字幕可以设置字体、大小、颜色、特效等多种参数,其格式大致如下:

[Script Info]
; This is an Advanced Sub Station Alpha v4+ script.
Title: subtitles
ScriptType: v4.00+
Collisions: Normal
PlayDepth: 0

[V4+ Styles]
Format: Name, Fontname, Fontsize, PrimaryColour,
SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline,
StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline,
Shadow, Alignment, MarginL, MarginR, MarginV, Encoding Style:
Default,Arial,20,&H00FFFFFF,&H0300FFFF,&H00000000,&H02000000,0,0,0,0,100,100,0,0,1,2,1,2,10,10,10,1

[Events]
Format: Layer, Start, End, Style, Actor, MarginL, MarginR,
MarginV, Effect, Text Dialogue:
0,0:00:01.00,0:00:02.00,Default,0,0,0,你好 Dialogue:
0,0:00:03.00,0:00:04.00,Default,0,0,0,这里是关于字幕格式转换的程序 Dialogue:
0,0:00:05.00,0:00:06.00,Default,0,0,0,我们会将纯文本的文件 Dialogue:
0,0:00:07.00,0:00:08.00,Default,0,0,0,直接转换为可识别的srt格式文件 Dialogue:
0,0:00:09.00,0:00:10.00,Default,0,0,0,以便于视频编辑文件识别字幕。

其中的[Script Info] 是基本信息介绍,[V4+ Styles] 是格式设置,[Events] 是字幕行的内容,我们可以看到其格式设置涉及非常多的参数,字体、文字位置、对齐方式、粗细等等,本例中在格式方面只使用默认,主要介绍如何生成ass格式文件。

txttoass代码:

def txt_to_ass(self,text,start_time,interval,font_name="Arial", font_size=20, color="#FFFFFF"): 
        """文本转ass"""
        # ASS文件的基本结构  
        ass_content = [   
            "[Script Info]", 
            "; This is an Advanced Sub Station Alpha v4+ script.", 
            "Title: subtitles", 
            "ScriptType: v4.00+", 
            "Collisions: Normal", 
            "PlayDepth: 0", 
            "\n", 
            "[V4+ Styles]", 
            "Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding", 
            "Style: Default,Arial,20,&H00FFFFFF,&H0300FFFF,&H00000000,&H02000000,0,0,0,0,100,100,0,0,1,2,1,2,10,10,10,1", 
            "[Events", 
            "Format: Layer, Start, End, Style, Actor, MarginL, MarginR, MarginV, Effect, Text", 
            "\n", 
            
        ]   
        lines=text.split('\n')
        #srt_lines = []   
        current_time = start_time   
        for line in lines: 
            line=line.strip()
            end_time=self.generate_timestamp_ass(current_time,interval)
            # 转换纯文本为ASS字幕  
            ass_content.append(