| 102 | } // namespace |
| 103 | |
| 104 | std::vector<SubtitleBlock> build_subtitle_blocks( |
| 105 | const std::vector<runtime::WordTimestamp> & words, |
| 106 | const SubtitleFormatOptions & options) { |
| 107 | validate_options(options); |
| 108 | if (words.empty()) { |
| 109 | return {}; |
| 110 | } |
| 111 | |
| 112 | const int64_t max_block_samples = seconds_to_samples(options.max_block_seconds, options.sample_rate); |
| 113 | const int64_t max_gap_samples = seconds_to_samples(options.max_gap_seconds, options.sample_rate); |
| 114 | std::vector<SubtitleBlock> blocks; |
| 115 | size_t block_begin = 0; |
| 116 | int64_t previous_start = 0; |
| 117 | |
| 118 | for (size_t i = 0; i < words.size(); ++i) { |
| 119 | validate_word(words[i], previous_start); |
| 120 | previous_start = words[i].span.start_sample; |
| 121 | |
| 122 | if (i == block_begin) { |
| 123 | continue; |
| 124 | } |
| 125 | |
| 126 | const bool gap_break = words[i].span.start_sample - words[i - 1].span.end_sample > max_gap_samples; |
| 127 | const bool duration_break = words[i].span.end_sample - words[block_begin].span.start_sample > max_block_samples; |
| 128 | const bool text_break = would_exceed_text_limit(words, block_begin, i + 1, options); |
| 129 | if (!gap_break && !duration_break && !text_break) { |
| 130 | continue; |
| 131 | } |
| 132 | |
| 133 | SubtitleBlock block; |
| 134 | block.index = static_cast<int>(blocks.size()) + 1; |
| 135 | block.span.start_sample = words[block_begin].span.start_sample; |
| 136 | block.span.end_sample = words[i - 1].span.end_sample; |
| 137 | block.lines = wrap_words(words, block_begin, i, options.max_chars_per_line); |
| 138 | blocks.push_back(std::move(block)); |
| 139 | block_begin = i; |
| 140 | } |
| 141 | |
| 142 | SubtitleBlock block; |
| 143 | block.index = static_cast<int>(blocks.size()) + 1; |
| 144 | block.span.start_sample = words[block_begin].span.start_sample; |
| 145 | block.span.end_sample = words.back().span.end_sample; |
| 146 | block.lines = wrap_words(words, block_begin, words.size(), options.max_chars_per_line); |
| 147 | blocks.push_back(std::move(block)); |
| 148 | return blocks; |
| 149 | } |
| 150 | |
| 151 | std::string format_srt( |
| 152 | const std::vector<runtime::WordTimestamp> & words, |