Merge master into feat/json-report, resolve CHANGES.TXT conflict

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Carlos Fernandez
2026-02-15 14:02:37 -08:00
4 changed files with 35 additions and 10 deletions

View File

@@ -28,6 +28,22 @@ The core functionality is written in C. Other languages used include C++ and Pyt
Downloads for precompiled binaries and source code can be found [on our website](https://ccextractor.org/public/general/downloads/).
### WebVTT Output Options
CCExtractor supports optional WebVTT-specific headers for advanced use cases
such as HTTP Live Streaming (HLS).
#### `--timestamp-map`
Enable writing the `X-TIMESTAMP-MAP` header in WebVTT output.
This header is required for HLS workflows but is **disabled by default**
to preserve compatibility with standard WebVTT players.
Example:
```bash
ccextractor input.ts --timestamp-map -o output.vtt
```
### Windows Package Managers
@@ -116,4 +132,4 @@ For more information visit the CCExtractor website: [https://www.ccextractor.org
## License
GNU General Public License version 2.0 (GPL-2.0)
GNU General Public License version 2.0 (GPL-2.0)

View File

@@ -1,8 +1,11 @@
0.96.6 (unreleased)
-------------------
- Add optional machine-readable JSON output for -out=report via --report-format json
- New: Add optional machine-readable JSON output for -out=report via --report-format json
- Fix: Incorrect strlen argument when writing end timestamps in MKV subtitle extraction (WebVTT, SRT, ASS/SSA)
- Fix: File descriptor leak and missing open() error check in MKV subtitle track saving
- Fix: DVB EIT start time BCD decoding in XMLTV output causing invalid timestamps (#1835)
- New: Add Snap packaging support with Snapcraft configuration and GitHub Actions CI workflow.
- New: Implement dictionary-based capitalization and censorship for transcripts
- Fix: Clear status line output on Linux/WSL to prevent text artifacts (#2017)
- Fix: Prevent infinite loop on truncated MKV files
- Fix: Various memory safety and stability fixes in demuxers (MP4, PS, MKV, DVB)

View File

@@ -120,11 +120,8 @@ int write_cc_subtitle_as_transcript(struct cc_subtitle *sub, struct encoder_ctx
start_time = sub->start_time;
end_time = sub->end_time;
}
if (context->sentence_cap)
{
// TODO capitalize (context, line_number,data);
// TODO correct_case_with_dictionary(line_number, data);
}
if (sub->data)
correct_spelling_and_censor_words(context, (unsigned char *)sub->data, strlen((char *)sub->data));
if (start_time == -1)
{

View File

@@ -1742,6 +1742,12 @@ void save_sub_track(struct matroska_ctx *mkv_ctx, struct matroska_sub_track *tra
free(filename);
}
if (desc < 0)
{
mprint("\nError: Cannot create output file for subtitle track\n");
return;
}
if (track->header != NULL)
write_wrapped(desc, track->header, strlen(track->header));
@@ -1795,7 +1801,7 @@ void save_sub_track(struct matroska_ctx *mkv_ctx, struct matroska_sub_track *tra
write_wrapped(desc, timestamp_start, strlen(timestamp_start));
write_wrapped(desc, " --> ", 5);
write_wrapped(desc, timestamp_end, strlen(timestamp_start));
write_wrapped(desc, timestamp_end, strlen(timestamp_end));
// writing cue settings list
if (blockaddition != NULL)
@@ -1836,7 +1842,7 @@ void save_sub_track(struct matroska_ctx *mkv_ctx, struct matroska_sub_track *tra
write_wrapped(desc, "\n", 1);
write_wrapped(desc, timestamp_start, strlen(timestamp_start));
write_wrapped(desc, " --> ", 5);
write_wrapped(desc, timestamp_end, strlen(timestamp_start));
write_wrapped(desc, timestamp_end, strlen(timestamp_end));
write_wrapped(desc, "\n", 1);
int size = 0;
while (*(sentence->text + size) == '\n' || *(sentence->text + size) == '\r')
@@ -1866,7 +1872,7 @@ void save_sub_track(struct matroska_ctx *mkv_ctx, struct matroska_sub_track *tra
write_wrapped(desc, "Dialogue: Marked=0,", strlen("Dialogue: Marked=0,"));
write_wrapped(desc, timestamp_start, strlen(timestamp_start));
write_wrapped(desc, ",", 1);
write_wrapped(desc, timestamp_end, strlen(timestamp_start));
write_wrapped(desc, timestamp_end, strlen(timestamp_end));
write_wrapped(desc, ",", 1);
char *text = ass_ssa_sentence_erase_read_order(sentence->text);
char *text_to_free = text; // Save original pointer for freeing
@@ -1880,6 +1886,9 @@ void save_sub_track(struct matroska_ctx *mkv_ctx, struct matroska_sub_track *tra
free(timestamp_end);
}
}
if (desc != 1)
close(desc);
}
void free_sub_track(struct matroska_sub_track *track)