From bb4743eb6fbc4af1c85dc7e0aeb92ee16919a56c Mon Sep 17 00:00:00 2001 From: Niki Roo Date: Mon, 16 May 2022 19:11:16 +0200 Subject: [PATCH] add webvtt read support, remove NOTE from webvtt write, some fixes, cleanup --- README-fr.md | 2 - README.md | 2 - src/nsub/nsub.c | 100 +++++++++++++++ src/nsub/nsub.h | 34 +++++ src/nsub/nsub_read_lrc.c | 186 ++++++++++++++------------- src/nsub/nsub_read_srt.c | 235 ++++++++++++++--------------------- src/nsub/nsub_read_webvtt.c | 205 ++++++++++++++++++++++++++++++ src/nsub/nsub_write_lrc.c | 29 ++++- src/nsub/nsub_write_srt.c | 6 +- src/nsub/nsub_write_webvtt.c | 16 ++- 10 files changed, 576 insertions(+), 239 deletions(-) create mode 100644 src/nsub/nsub_read_webvtt.c diff --git a/README-fr.md b/README-fr.md index e665ab6..4896417 100644 --- a/README-fr.md +++ b/README-fr.md @@ -25,8 +25,6 @@ Il ne nécessite pas de librairies externes. - `SRT` fichiers sous-titres SubRip, ils accompagnent en général des films - `WebVTT` Web Video Text Tracks, un nouveau standard W3C -Note : ce programme ne peut pas encore ouvrir des fichiers WebVTT (il supporte toutefois les 3 formats en écriture) - ## Options - **--help** (or **-h**) : information sur la syntaxe du programme diff --git a/README.md b/README.md index 7642dcc..1468cd7 100644 --- a/README.md +++ b/README.md @@ -25,8 +25,6 @@ It does not require external libraries. - `SRT` SubRip subtitle files, usually distributed with films - `WebVTT` Web Video Text Tracks, a new W3C standard -Note: this program can not yet open WebVTT files (it supports all 3 formats as output, though) - ## Options - **--help** (or **-h**): information about the syntax diff --git a/src/nsub/nsub.c b/src/nsub/nsub.c index 221aeb1..3df4da0 100644 --- a/src/nsub/nsub.c +++ b/src/nsub/nsub.c @@ -115,6 +115,9 @@ song_t *nsub_read(FILE *in, NSUB_FORMAT fmt) { case NSUB_FMT_SRT: read_a_line = nsub_read_srt; break; + case NSUB_FMT_WEBVTT: + read_a_line = nsub_read_webvtt; + break; default: fprintf(stderr, "Unsupported read format %d\n", fmt); goto fail; @@ -153,3 +156,100 @@ int nsub_write(FILE *out, song_t *song, NSUB_FORMAT fmt, int apply_offset) { return 0; } } + +int nsub_to_ms(const char line[], char deci_sym) { + // 00:00:17,400 + + /* should not happen! */ + /* note: also, we assume max 3 decimal digits */ + if (!nsub_is_timing(line, deci_sym, 3)) { + fprintf(stderr, + "Warning: called nsub_to_ms with bad input [%s], ignoring...\n", + line); + return 0; + } + + int mults[] = { 1, 1000, 60000, 3600000 }; + + int group[4] = { 0, 0, 0, 0 }; + int igroup = -1; + + char mtmp[3] = { 1, 10, 100 }; + int itmp = 0; + + int has_milli = 0; + + size_t end = strlen(line) - 1; + + for (size_t i = end; i >= 0; i--) { + char car = line[i]; + + int digit = (car >= '0' && car <= '9'); + int dot = car == deci_sym; + int col = (car == ':'); + + if (!digit && !dot && !col) { + break; + } + + if (digit) { + if (itmp == 0) + igroup++; + + group[igroup] += mtmp[itmp] * (car - (int) '0'); + itmp++; + } else { + if (dot) + has_milli = 1; + + itmp = 0; + } + } + + int total = 0; + int multOffset = (has_milli ? 0 : 1); + for (int i = 0; i <= igroup; i++) { + total += mults[i + multOffset] * group[i]; + } + + return total; +} + +int nsub_is_timing(const char line[], char deci_sym, int max_deci) { + // 00:00:14,800 + + int digits = 0; + int groups = 0; + int sep = 0; + + int max_digits = 2; + int max_groups = 3; + + for (char *ptr = (char *) line; *ptr; ptr++) { + int digit = (*ptr >= '0' && *ptr <= '9'); + int col = (*ptr == ':'); + int dot = *ptr == deci_sym; + + if (digit) { + digits++; + } else if (col) { + digits = 0; + groups++; + } else if (dot) { + digits = 0; + max_digits = max_deci; + sep++; + } else { + return 0; + } + + if (digits > max_digits) + return 0; + if (groups > max_groups) + return 0; + if (sep > 1) + return 0; + } + + return 1; +} diff --git a/src/nsub/nsub.h b/src/nsub/nsub.h index 008b1cc..1704437 100644 --- a/src/nsub/nsub.h +++ b/src/nsub/nsub.h @@ -146,6 +146,40 @@ void song_add_meta(song_t *song, char *key, char *value); /* Read */ +/** + * Convert a text line into milliseconds (for instance, 00:00:17,400). + * Text must be conform, though less groups or less digits per group + * is allowed. + * + * @note maximum number of groups: 4, + * maximum number of digits per + * group: 2 except decimal group which is allowed up to 3 + * + * @param line the line to convert + * @param deci_sep the decimal separator symbol (usually '.' or ',') + * @param max_deci maximum number of digits for the decimal value (max is 3) + * + * @return the number of milliseconds it means + */ +int nsub_to_ms(const char line[], char deci_sym); + +/** + * Validate that the given line is a timing (for instance, 00:00:17,400). + * Text must be conform, though less groups or less digits per group + * is allowed. + * + * @note maximum number of groups: 4, + * maximum number of digits per + * group: 2 except decimal group which is allowed up to 3 + * + * @param line the line to check + * @param deci_sep the decimal separator symbol (usually '.' or ',') + * @param max_deci maximum number of digits for the decimal value + * + * @return TRUE if it is + */ +int nsub_is_timing(const char line[], char deci_sym, int max_deci); + song_t *nsub_read(FILE *in, NSUB_FORMAT fmt); int nsub_read_lrc(song_t *song, char *line); int nsub_read_webvtt(song_t *song, char *line); diff --git a/src/nsub/nsub_read_lrc.c b/src/nsub/nsub_read_lrc.c index 35cbb15..796424c 100644 --- a/src/nsub/nsub_read_lrc.c +++ b/src/nsub/nsub_read_lrc.c @@ -25,13 +25,13 @@ /* Declarations */ // test if this is an offset line -int is_lrc_offset(char *line); +static int is_lrc_offset(char *line); // test if it is a timed lyric -int is_lrc_lyric(char *line, int*end); +static int is_lrc_lyric(char *line, int*end); // test if this is a meta line -int is_lrc_meta(char *line, int *colon, int *end); +static int is_lrc_meta(char *line, int *colon, int *end); // count the ms in the line "[(00:0)0:14.80]" or "[offset: +0:12]" -int lrc_millisec(char *line); +static int lrc_millisec(char *line); /* Public */ @@ -106,48 +106,79 @@ int nsub_read_lrc(song_t *song, char *line) { /* Private */ -int is_lrc_offset(char *line) { - const char offset[] = { "[offset" }; - int i = 0; - while (line[i] && offset[i] && line[i] == offset[i]) - i++; +static int is_lrc_offset(char *line) { + // [offset: +0:12] - if (!offset[i]) { - while (line[i] == ' ') - i++; + // skip spaces + while (*line == ' ') + line++; - if (line[i] == ':') - return 1; + // skip [offset + char *offset = { "[offset" }; + while (*line && *offset && *offset == *line) { + line++; + offset++; } + if (*offset) + return 0; - return 0; -} + // skip spaces then ':' + while (*line == ' ') + line++; + if (*line && *line != ':') + return 0; + line++; -int is_lrc_lyric(char *line, int *end) { - if (line[0] != '[') + // allow sign + if (*line == '-' || *line == '+') + line++; + while (*line == ' ') + line++; + + // find end + int i = 0; + while (line[i] && line[i] != ']') + i++; + if (line[i] != ']') return 0; - *end = 0; + // validate timing + cstring_t*tmp = cstring_substring(line, 0, i); + int ok = nsub_is_timing(tmp->string, '.', 2); + free_cstring(tmp); + return ok; +} - for (int i = 1; line[i]; i++) { - char car = line[i]; +static int is_lrc_lyric(char *line, int *end) { + // "[(00:0)0:14.80] bla bla bla" - if (car == ']') { - *end = i; - return i >= 2; - } + *end = 0; - int digit = (car >= '0' && car <= '9'); - int sep = (car == ':' || car == '.' || car == ' '); + // skip spaces + while (*line == ' ') + line++; - if (!digit && !sep) - break; - } + // skip [ + if (*line != '[') + return 0; + line++; + + // find end + int i = 0; + while (line[i] && line[i] != ']') + i++; + if (line[i] != ']') + return 0; + *end = i; - return 0; + // validate timing + cstring_t*tmp = cstring_substring(line, 0, i); + int ok = nsub_is_timing(tmp->string, '.', 2); + free_cstring(tmp); + return ok; } -int is_lrc_meta(char *line, int *colon, int *end) { +static int is_lrc_meta(char *line, int *colon, int *end) { if (line[0] != '[') return 0; @@ -169,63 +200,50 @@ int is_lrc_meta(char *line, int *colon, int *end) { return (*colon) && (*end); } -int lrc_millisec(char *line) { - int mults[] = { 1000, 10000, 60000, 600000, 3600000, 36000000 }; +static int lrc_millisec(char *line) { + // count the ms in the line "[(00:0)0:14.80]" or "[offset: +0:12]" - size_t end = 0; - for (size_t i = 0; line[i]; i++) { - if (line[i] == ']') { - end = i - 1; - break; - } - } - - int total = 0; - for (size_t i = end; i >= 0; i--) { - char car = line[i]; - - int digit = (car >= '0' && car <= '9'); - int sign = (car == '-' || car == '+'); - int dot = car == '.'; - int col = (car == ':'); + int sign = 1; + int dummy = 0; - if (!digit && !sign && !dot && !col) { - break; - } - - if (dot) { - int mult = 1; - - int j = i + 3; - while (j > end) { - mult *= 10; - j--; - } - - for (; j > i; j--) { - total += mult * ((int) line[j] - (int) '0'); - mult *= 10; - } + // skip spaces + while (*line == ' ') + line++; - end = i - 1; - break; + if (is_lrc_lyric(line, &dummy)) { + // skip [ + line++; + } else if (is_lrc_offset(line)) { + // skip [offset: + while (*line != ':') + line++; + while (*line == ' ') + line++; + + // allow sign + if (*line == '+') { + line++; + } else if (*line == '-') { + line++; + sign = -1; } + while (*line == ' ') + line++; + } else { + /* should not happen! */ + fprintf(stderr, + "Warning: called lrc_millisec with bad input [%s], ignoring...\n", + line); + return 0; } - int imult = 0; - for (size_t i = end; 1; i--) { - char car = line[i]; - int digit = (car >= '0' && car <= '9'); - - if (digit) - total += (car - '0') * mults[imult++]; - - if (car == '-') - total = -total; - - if (i == 0) - break; - } + // find end + int i = 0; + while (line[i] != ']') + i++; - return total; + cstring_t*tmp = cstring_substring(line, 0, i); + int ms = nsub_to_ms(tmp->string, '.'); + free_cstring(tmp); + return sign * ms; } diff --git a/src/nsub/nsub_read_srt.c b/src/nsub/nsub_read_srt.c index 23ed04f..30becc4 100644 --- a/src/nsub/nsub_read_srt.c +++ b/src/nsub/nsub_read_srt.c @@ -25,11 +25,10 @@ /* Declarations */ -static int is_srt_id(const char line[]); -static int is_srt_timing(const char line[]); -static int get_start(const char line[]); -static int get_stop(const char line[]); -static int to_ms(const char line[]); +static int is_srt_id(char *line); +static int is_srt_timing(char *line); +static int get_start(char *line); +static int get_stop(char *line); int nsub_read_srt(song_t *song, char *line) { int empty = 1; @@ -48,15 +47,15 @@ int nsub_read_srt(song_t *song, char *line) { if (is_srt_id(line)) { int new_count = atoi(line); - if (new_count != count + 1) { fprintf(stderr, - "Warning: line %zu is out of order (it is numbered %i), ignoring order...", + "Warning: line %zu is out of order (it is numbered %i), ignoring order...\n", count, new_count); } song_add_lyric(song, 0, 0, NULL, NULL); } else if (is_srt_timing(line)) { + // no headers in srt if (!lyric) { return 0; } @@ -70,7 +69,7 @@ int nsub_read_srt(song_t *song, char *line) { char *text = lyric->text; if (text) - text = cstring_concat(text, "\n", line); + text = cstring_concat(text, "\n", line, NULL); else text = strdup(line); @@ -83,7 +82,7 @@ int nsub_read_srt(song_t *song, char *line) { /* Private */ -static int is_srt_id(const char line[]) { +static int is_srt_id(char *line) { for (char *ptr = (char *) line; *ptr; ptr++) { switch (*ptr) { case '0': @@ -106,161 +105,115 @@ static int is_srt_id(const char line[]) { return 1; } -static int is_srt_timing(const char line[]) { +static int is_srt_timing(char *line) { // Canonical example: - // 00:00:14,800 --> 00:00:17,400 - - int vals = 0; - int vals_groups = 0; - int sep = 0; - int deci = 0; - - for (char *ptr = (char *) line; *ptr; ptr++) { - switch (*ptr) { - case ' ': // ignore space if not in sep - if (sep && sep < 2) - return 0; - break; - - case '0': // count a new numeric - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - vals++; - break; - - case ',': // we just did a group - case ':': - if (*ptr == ',') - deci = 1; - - if (vals < 1 || vals > 2) - return 0; - - vals = 0; - vals_groups++; - break; + // 00:00:14,800 --> 00:00:17,400 align: center - case '-': // Separator (-->) - if (!sep) { - vals_groups++; + cstring_t *tmp; + int ok; + int i; - if (vals < 1 || (vals > 2 && !deci) || vals > 3) - return 0; + // skip spaces + while (*line == ' ') + line++; - if (vals_groups < 1 || (vals_groups > 3 && !deci) - || vals_groups > 4) - return 0; - - vals = 0; - vals_groups = 0; - deci = 0; - } + // check part 1 + i = 0; + while (line[i] && line[i] != ' ' && line[i] != '-') + i++; + if (line[i] != ' ' && line[i] != '-') + return 0; + tmp = cstring_substring(line, 0, i); + ok = nsub_is_timing(tmp->string, ',', 3); + free_cstring(tmp); + if (!ok) + return 0; - if (sep > 2) - return 0; + // skip part 1 + line += i; - sep++; - break; + // skip spaces + while (*line == ' ') + line++; - case '>': // Separator (-->) - if (sep != 2) - return 0; - - sep++; - break; - } + // skip --> + char *arrow = { "-->" }; + while (*line && *arrow && *arrow == *line) { + line++; + arrow++; } - - if (vals < 1 || (vals > 2 && !deci) || vals > 3) + if (*arrow) return 0; - if (vals_groups < 1 || (vals_groups > 3 && !deci) || vals_groups > 4) - return 0; + // skip spaces + while (*line == ' ') + line++; - if (sep != 3) - return 0; + // find end + i = 0; + while (line[i] && line[i] != ' ') + i++; - return 1; + // validate part 2 + tmp = cstring_substring(line, 0, i); + ok = nsub_is_timing(tmp->string, ',', 3); + free_cstring(tmp); + return !!ok; } -static int get_start(const char line[]) { - char *ptr = (char *) line; - while (*ptr == ' ') - ptr++; +static int get_start(char *line) { + // 00:00:14,800 --> 00:00:17,400 align: center - size_t i; - for (i = 0; ptr[i] != ' ' && ptr[i] != '-'; i++) - ; + if (!is_srt_timing(line)) { + /* should not happen! */ + fprintf(stderr, + "Warning: called get_start with bad input [%s], ignoring...\n", + line); + return 0; + } - cstring_t*start = cstring_substring(ptr, 0, i); - int ms = to_ms(start->string); - free_cstring(start); - return ms; -} + // skip spaces + while (*line == ' ') + line++; -static int get_stop(const char line[]) { - char *ptr = (char *) line; - while (*ptr != '>') - ptr++; - ptr++; - while (*ptr == ' ') - ptr++; + // find end + int i = 0; + while (line[i] && line[i] != ' ' && line[i] != '-') + i++; - return to_ms(ptr); + cstring_t*start = cstring_substring(line, 0, i); + int ms = nsub_to_ms(start->string, ','); + free_cstring(start); + return ms; } -static int to_ms(const char line[]) { - // 00:00:17,400 - - int mults[] = { 1, 1000, 60000, 3600000 }; - - int group[4] = { 0, 0, 0, 0 }; - int igroup = -1; - - char mtmp[3] = { 1, 10, 100 }; - int itmp = 0; +static int get_stop(char *line) { + // 00:00:14,800 --> 00:00:17,400 align: center - int has_milli = 0; - - size_t end = strlen(line) - 1; - - for (size_t i = end; i >= 0; i--) { - char car = line[i]; - - int digit = (car >= '0' && car <= '9'); - int dot = car == ','; - int col = (car == ':'); - - if (!digit && !dot && !col) { - break; - } - - if (digit) { - if (itmp == 0) - igroup++; + if (!is_srt_timing(line)) { + /* should not happen! */ + fprintf(stderr, + "Warning: called get_stop with bad input [%s], ignoring...\n", + line); + return 0; + } - group[igroup] += mtmp[itmp] * (car - (int) '0'); - itmp++; - } else { - if (dot) - has_milli = 1; + // skip to > + while (*line != '>') + line++; + line++; - itmp = 0; - } - } + // skip spaces + while (*line == ' ') + line++; - int total = 0; - int multOffset = (has_milli ? 0 : 1); - for (int i = 0; i <= igroup; i++) { - total += mults[i + multOffset] * group[i]; - } + // find end + int i = 0; + while (line[i] && line[i] != ' ') + i++; - return total; + cstring_t*end = cstring_substring(line, 0, i); + int ms = nsub_to_ms(end->string, ','); + free_cstring(end); + return ms; } diff --git a/src/nsub/nsub_read_webvtt.c b/src/nsub/nsub_read_webvtt.c new file mode 100644 index 0000000..35a3977 --- /dev/null +++ b/src/nsub/nsub_read_webvtt.c @@ -0,0 +1,205 @@ +/* + * NSub: Subtitle/Lyrics conversion program (webvtt/srt/lrc) + * + * Copyright (C) 2022 Niki Roo + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include + +#include "nsub.h" +#include "utils/utils.h" + +/* Declarations */ + +static int is_srt_id(char *line); +static int is_srt_timing(char *line); +static int get_start(char *line); +static int get_stop(char *line); + +int nsub_read_webvtt(song_t *song, char *line) { + int empty = 1; + for (int i = 0; empty && line[i]; i++) { + if (line[i] != ' ') + empty = 0; + } + + if (empty) + return 1; + + size_t count = array_count(song->lyrics); + lyric_t *lyric = NULL; + if (count) + lyric = array_get(song->lyrics, array_count(song->lyrics) - 1); + + if (is_srt_id(line)) { + int new_count = atoi(line); + if (new_count != count + 1) { + fprintf(stderr, + "Warning: line %zu is out of order (it is numbered %i), ignoring order...\n", + count, new_count); + } + } else if (is_srt_timing(line)) { + song_add_lyric(song, 0, 0, NULL, NULL); + lyric = array_get(song->lyrics, array_count(song->lyrics) - 1); + + lyric->start = get_start(line); + lyric->stop = get_stop(line); + } else { + // a header has been found + if (!lyric) { + return 1; + } + + char *text = lyric->text; + if (text) + text = cstring_concat(text, "\n", line, NULL); + else + text = strdup(line); + + free(lyric->text); + lyric->text = text; + } + + return 1; +} + +/* Private */ + +static int is_srt_id(char *line) { + for (char *ptr = (char *) line; *ptr; ptr++) { + int digit = (*ptr >= '0' && *ptr <= '9'); + int space = (*ptr == ' '); + + if (!digit && !space) + return 0; + } + + return 1; +} + +static int is_srt_timing(char *line) { + // Canonical example: + // 00:00:14.800 --> 00:00:17.400 align: center + + cstring_t *tmp; + int ok; + int i; + + // skip spaces + while (*line == ' ') + line++; + + // check part 1 + i = 0; + while (line[i] && line[i] != ' ' && line[i] != '-') + i++; + if (!line[i]) + return 0; + tmp = cstring_substring(line, 0, i); + ok = nsub_is_timing(tmp->string, '.', 3); + free_cstring(tmp); + if (!ok) + return 0; + + // skip part 1 + line += i; + + // skip spaces + while (*line == ' ') + line++; + + // skip --> + char *arrow = { "-->" }; + while (*line && *arrow && *arrow == *line) { + line++; + arrow++; + } + if (*arrow) + return 0; + + // skip spaces + while (*line == ' ') + line++; + + // find end + i = 0; + while (line[i] && line[i] != ' ') + i++; + + // validate part 2 + tmp = cstring_substring(line, 0, i); + ok = nsub_is_timing(tmp->string, '.', 3); + free_cstring(tmp); + return !!ok; +} + +static int get_start(char *line) { + // 00:00:14,800 --> 00:00:17,400 align: center + + if (!is_srt_timing(line)) { + /* should not happen! */ + fprintf(stderr, + "Warning: called get_start with bad input [%s], ignoring...\n", + line); + return 0; + } + + // skip spaces + while (*line == ' ') + line++; + + // find end + int i = 0; + while (line[i] && line[i] != ' ' && line[i] != '-') + i++; + + cstring_t*start = cstring_substring(line, 0, i); + int ms = nsub_to_ms(start->string, '.'); + free_cstring(start); + return ms; +} + +static int get_stop(char *line) { + // 00:00:14,800 --> 00:00:17,400 align: center + + if (!is_srt_timing(line)) { + /* should not happen! */ + fprintf(stderr, + "Warning: called get_stop with bad input [%s], ignoring...\n", + line); + return 0; + } + + // skip to > + while (*line != '>') + line++; + line++; + + // skip spaces + while (*line == ' ') + line++; + + // find end + int i = 0; + while (line[i] && line[i] != ' ') + i++; + + cstring_t*end = cstring_substring(line, 0, i); + int ms = nsub_to_ms(end->string, '.'); + free_cstring(end); + return ms; +} diff --git a/src/nsub/nsub_write_lrc.c b/src/nsub/nsub_write_lrc.c index a7224b2..9d391f3 100644 --- a/src/nsub/nsub_write_lrc.c +++ b/src/nsub/nsub_write_lrc.c @@ -20,6 +20,7 @@ #include #include "nsub.h" +#include "utils/utils.h" /* Declarations */ @@ -88,17 +89,37 @@ void nsub_write_lrc_lyric(FILE *out, lyric_t *lyric, int offset) { } if (lyric->type == NSUB_COMMENT || lyric->type == NSUB_UNKNOWN) { - fprintf(out, "-- %s\n", lyric->text); + cstring_t *tmp = cstring_clone(lyric->text); + if (tmp) { + cstring_replace(tmp, "\n", "\\n"); + } + + fprintf(out, "-- %s\n", tmp->string); lrc_last_stop = 0; + + free_cstring(tmp); return; } - if (lyric->name) - fprintf(out, "-- %s\n", lyric->name); + if (lyric->name) { + cstring_t *tmp = cstring_clone(lyric->name); + if (tmp) { + cstring_replace(tmp, "\n", "\\n"); + } + + fprintf(out, "-- %s\n", tmp->string); + + free_cstring(tmp); + } char *time = nsub_lrc_time_str(lyric->start + offset, 0); - fprintf(out, "[%s] %s\n", time, lyric->text); + cstring_t *tmp = cstring_clone(lyric->text); + if (tmp) { + cstring_replace(tmp, "\n", "\\n"); + } + fprintf(out, "[%s] %s\n", time, tmp->string); free(time); + free_cstring(tmp); lrc_last_stop = lyric->stop + offset; } diff --git a/src/nsub/nsub_write_srt.c b/src/nsub/nsub_write_srt.c index 57743a9..141bdb1 100644 --- a/src/nsub/nsub_write_srt.c +++ b/src/nsub/nsub_write_srt.c @@ -20,6 +20,7 @@ #include #include "nsub.h" +#include "utils/utils.h" /* Declarations */ @@ -64,12 +65,15 @@ void nsub_write_srt_lyric(FILE *out, lyric_t *lyric, int offset) { return; } + // Num is mandatory for srt + fprintf(out, "%d\n", lyric->num); + //if (lyric->name) // not supported, ignored char *start = nsub_srt_time_str(lyric->start + offset, 0); char *stop = nsub_srt_time_str(lyric->stop + offset, 0); - fprintf(out, "%d\n%s --> %s\n%s\n\n", lyric->num, start, stop, lyric->text); + fprintf(out, "%s --> %s\n%s\n\n", start, stop, lyric->text); free(start); free(stop); } diff --git a/src/nsub/nsub_write_webvtt.c b/src/nsub/nsub_write_webvtt.c index b73090b..1b6c571 100644 --- a/src/nsub/nsub_write_webvtt.c +++ b/src/nsub/nsub_write_webvtt.c @@ -43,7 +43,8 @@ int nsub_write_webvtt(FILE *out, song_t *song, NSUB_FORMAT fmt, // metas array_loop(song->metas, meta, meta_t) { - fprintf(out, "NOTE META %s: %s\n\n", meta->key, meta->value); + // Not always supported by clients, so disabled: + //fprintf(out, "NOTE META %s: %s\n\n", meta->key, meta->value); } // offset is not supported in WebVTT (so, always applied) @@ -53,8 +54,9 @@ int nsub_write_webvtt(FILE *out, song_t *song, NSUB_FORMAT fmt, // other metas { - fprintf(out, - "NOTE META created by: nsub (https://github.com/nikiroo/nsub)]\n"); + // Not always supported by clients, so disabled: + //fprintf(out, + // "NOTE META created by: nsub (https://github.com/nikiroo/nsub)]\n"); } // lyrics @@ -79,8 +81,12 @@ void nsub_write_webvtt_lyric(FILE *out, lyric_t *lyric, int offset) { return; } - if (lyric->name) - fprintf(out, "%s\n", lyric->name); + // Num is optional for WebVTT, but maybe easier for clients + fprintf(out, "%d\n", lyric->num); + + // Not always supported by clients, so disabled: + // if (lyric->name) + //fprintf(out, "%s\n", lyric->name); char *start = nsub_webvtt_time_str(lyric->start + offset, 0); char *stop = nsub_webvtt_time_str(lyric->stop + offset, 0); -- 2.27.0