///|
/// SRT字幕处理库 - 用于创建、解析和格式化SRT字幕文件
///
/// 本模块提供了完整的SRT字幕处理功能,包括:
/// 1. SRT字幕文件的创建和管理
/// 2. 字幕片段的定义和操作
/// 3. 时间格式转换(秒到HMS格式)
/// 4. 标准Show trait实现,支持格式化输出
///
/// 主要类型:
/// - `Srt`: SRT字幕文件的容器,包含多个字幕片段
/// - `Piece`: 单个字幕片段,包含序号、时间信息和文本内容
///
/// 使用示例:
/// ```moonbit
/// let srt = Srt::new()
/// let piece = Piece::new(1, 0, 5, "Hello, World!")
/// srt.add_piece(piece)
/// println(srt) // 输出格式化的SRT内容
/// ```
///|
/// SRT文件中的字幕片段,包含时间和内容信息。
///
/// 字段:
///
/// * `index` : 字幕片段的序号。
/// * `start` : 开始时间,以秒为单位。
/// * `end` : 结束时间,以秒为单位。
/// * `text` : 字幕内容文本。
///
///|
/// ```
///
pub(all) struct Piece {
index : Int
// 开始时间,秒
start : Int
// 结束时间,秒
end : Int
text : String
}
///|
/// SRT字幕文件的容器结构体。
///
/// 包含一个字幕片段数组,用于存储和管理整个SRT文件的内容。
/// 每个SRT文件由多个按时间顺序排列的字幕片段组成。
///
/// 字段:
/// * `pieces` : 字幕片段数组,按时间顺序存储所有字幕片段。
pub(all) struct Srt {
pieces : Array[Piece]
}
///|
/// 创建一个新的空SRT文件。
///
/// 返回一个不包含任何字幕片段的`Srt`实例。
///
/// 示例:
/// ```moonbit nocheck
/// let srt = Srt::new()
/// inspect(srt.pieces.length(), content="0")
/// ```
pub fn Srt::new() -> Srt {
Srt::{ pieces: Array::new() }
}
///|
/// 向SRT文件中添加一个字幕片段。
///
/// 参数:
/// * `self` : 要添加字幕片段的SRT文件
/// * `piece` : 要添加的字幕片段
///
/// 注意:片段将按添加顺序存储,调用者应确保时间顺序正确。
///
/// 示例:
/// ```moonbit nocheck
/// let srt = Srt::new()
/// let piece = Piece::new(1, 0, 5, "Hello")
/// srt.add_piece(piece)
/// inspect(srt.pieces.length(), content="1")
/// ```
pub fn Srt::add_piece(self : Srt, piece : Piece) -> Unit {
self.pieces.push(piece)
}
///|
/// 创建一个新的字幕片段。
///
/// 参数:
/// * `index` : 字幕片段的序号(从1开始)
/// * `start` : 开始时间,以秒为单位
/// * `end` : 结束时间,以秒为单位
/// * `text` : 字幕内容文本
///
/// 返回一个新的`Piece`实例。
///
/// 示例:
/// ```moonbit nocheck
/// let piece = Piece::new(1, 0, 5, "Hello, World!")
/// inspect(piece.index, content="1")
/// inspect(piece.start, content="0")
/// inspect(piece.end, content="5")
/// inspect(piece.text, content="Hello, World!")
/// ```
pub fn Piece::new(index : Int, start : Int, end : Int, text : String) -> Piece {
Piece::{ index, start, end, text }
}
// If you want to implement the standard Show trait:
///|
/// 为 `Piece` 实现 `Show` 特征,提供 SRT 字幕格式的格式化字符串表示。
///
/// 参数:
///
/// * `self`:要格式化的字幕片段。
/// * `logger`:用于写入格式化字符串的输出日志器。
///
///
pub impl Show for Piece with output(self, logger) -> Unit {
let res =
$|\{self.index}
$|\{Piece::sec_to_hms(self.start)} --> \{Piece::sec_to_hms(self.end)}
$|\{self.text}
#|
logger.write_string(res)
}
///|
pub impl Show for Srt with output(self, logger) -> Unit {
self.pieces.each(fn(piece) {
let res =
$|\{piece.index}
$|\{Piece::sec_to_hms(piece.start)} --> \{Piece::sec_to_hms(piece.end)}
$|\{piece.text}
#|
logger.write_string(res)
})
}
// If you want a custom output method with logger:
///|
/// 将秒数转换为 HMS(小时:分钟:秒)格式,并附加毫秒占位符,用于 SRT 字幕时间戳。
///
/// 参数:
/// * `sec` : 要转换的时间长度(以秒为单位)。
///
/// 返回适用于 SRT 字幕文件的 "HH:MM:SS,000" 格式字符串。
///
/// 算法说明:
/// 1. 计算小时数:`hour = sec / 3600`
/// 2. 计算分钟数:`minute = (sec % 3600) / 60`
/// 3. 计算秒数:`second = sec % 60`
/// 4. 将各部分格式化为2位数字,不足2位时前面补0
/// 5. 组合为 "HH:MM:SS,000" 格式(毫秒部分固定为000)
///
/// 示例:
/// ```moonbit nocheck
/// inspect(Piece::sec_to_hms(0), content="00:00:00,000")
/// inspect(Piece::sec_to_hms(65), content="00:01:05,000")
/// inspect(Piece::sec_to_hms(3665), content="01:01:05,000")
/// ```
fn Piece::sec_to_hms(sec : Int) -> String {
let hour = sec / 3600
let minute = sec % 3600 / 60
let second = sec % 60
// 辅助函数:将数字格式化为2位字符串,不足2位时前面补0
fn pad_hms(val : Int) -> String {
return val.to_string().pad_start(2, '0')
}
let h_str = pad_hms(hour)
let m_str = pad_hms(minute)
let s_str = pad_hms(second)
return "\{h_str}:\{m_str}:\{s_str},000"
}