Разберите файл SRT с помощью jQuery Javascript

Я пытаюсь разобрать .srt, но получаю внутреннюю ошибку и не могу понять, что это такое.

Вот мой код:

    var subtitles;
    jQuery.get('SB_LKRG-eng.srt', function(data) {
        //alert(data);
        function strip(s) {
            return s.replace(/^\s+|\s+$/g,"");
        }
        srt = data.replace(/\r\n|\r|\n/g, '\n');
        //alert(srt);
        srt = strip(srt);
        //alert(srt);
        var srt_ = srt.split('\n\n');
        alert(srt_);
        var cont = 0;
        for(s in srt_) {
            st = srt_[s].split('\n');
            alert(st);
            if(st.length >=2) {
              n = st[0];
              i = strip(st[1].split(' --> ')[0]);
              o = strip(st[1].split(' --> ')[1]);
              t = st[2];

              if(st.length > 2) {
                for(j=3; j<st.length;j++)
                  t += '\n'+st[j];
              }

            subtitles[cont].number = n;
            subtitles[cont].start = i;
            subtitles[cont].end = o;
            subtitles[cont].text = t;
            //alert(subtitles[cont].start);
            }
            cont++;
        }

    });

Я могу извлечь первые 4 субтитров, а затем код останавливается и ломает exception: TypeError, я не могу понять, почему... Вот пример файла субтитров:

1
00:00:01,000 --> 00:00:04,000
Descargados de www.AllSubs.org

2
00:00:49,581 --> 00:00:52,049
Bueno, tienes que escapar, tengo que ir a jugar

3
00:00:52,084 --> 00:00:55,178
Tengo que encontrar un día que está lleno de nada más que sol

4
00:00:55,220 --> 00:00:57,552
Crucero por la calle, moviéndose al compás

5
00:00:57,589 --> 00:01:00,683
Todos los que conoces está teniendo nada más que diversión

6
00:01:00,726 --> 00:01:03,251
Deja todo detrás de ti

7
00:01:03,295 --> 00:01:06,128
Siente esas palmeras soplan

8
00:01:06,165 --> 00:01:09,157
La gente en el norte no puede encontrar

9
00:01:09,201 --> 00:01:11,829
Están fuera de palear la nieve

10
00:01:11,870 --> 00:01:14,998
El tiempo para moverse, pero no seas lento

11
00:01:15,040 --> 00:01:17,941
En sus marcas, prepárate para ir

Часть кода взята из: http://v2v.cc/~j/jquery.srt/jquery.srt.js

Может кто-нибудь помочь мне?

Спасибо


person Sergi    schedule 15.10.2015    source источник
comment
Не могли бы вы опубликовать содержимое .srt файла (или его части)?   -  person hindmost    schedule 15.10.2015
comment
@hindmost Я разместил образец файла .srt, спасибо!   -  person Sergi    schedule 15.10.2015
comment
@LGSon Я отредактировал пост, потому что эта функция не важна для моей проблемы, спасибо!!   -  person Sergi    schedule 15.10.2015
comment
Разве cont++; не должно быть внутри цикла for?   -  person Ason    schedule 15.10.2015
comment
@LGSon да, это внутри   -  person Sergi    schedule 15.10.2015
comment
Извините, я упоминаю внутри оператора if(st.length >=2) {?   -  person Ason    schedule 15.10.2015
comment
@LGSon спасибо за ответ. Я думаю, что cont++ должен быть вне if(st.length), потому что мне нужно одно и то же количество для каждой итерации, потому что subtitles - это массив кортежей, где внутри каждой позиции есть 4 поля, и мне нужно одно и то же число счета, чтобы записать каждое поле одной позиции , я прав?   -  person Sergi    schedule 15.10.2015
comment
Используйте метод push вместо серий заданий   -  person hindmost    schedule 15.10.2015
comment
Теперь, когда cont++ находится за пределами первого if(st.length >=2) {, вы всегда считаете, но сохраняете в subtitles[cont] только тогда, когда if(st.length >=2) истинно. ... Обратите внимание, что я не имею в виду внутреннюю if(st.length > 2) {   -  person Ason    schedule 15.10.2015


Ответы (3)


var PF_SRT = function() {
  //SRT format
  var pattern = /(\d+)\n([\d:,]+)\s+-{2}\>\s+([\d:,]+)\n([\s\S]*?(?=\n{2}|$))/gm;
  var _regExp;

  var init = function() {
    _regExp = new RegExp(pattern);
  };
  var parse = function(f) {
    if (typeof(f) != "string")
      throw "Sorry, Parser accept string only.";

    var result = [];
    if (f == null)
      return _subtitles;

    f = f.replace(/\r\n|\r|\n/g, '\n')

    while ((matches = pattern.exec(f)) != null) {
      result.push(toLineObj(matches));
    }
    return result;
  }
  var toLineObj = function(group) {
    return {
      line: group[1],
      startTime: group[2],
      endTime: group[3],
      text: group[4]
    };
  }
  init();
  return {
    parse: parse
  }
}();

 

  jQuery.get('demo.srt')
   .done(function(text) {
       try {
         //Array with {line, startTime, endTime, text}
         var result = PF_SRT.parse(text);
       } catch (e) {
         //handle parsing error
       }
  });

Демо

https://jsfiddle.net/5v7wz4bq/

person Parfait    schedule 15.10.2015
comment
Когда я запускаю ваш код в этой демонстрации скрипки, jsfiddle.net/876sscf7/4, возникает ошибка в середине первой итерации. Не могли бы вы объяснить, почему ваша демонстрация не работает? ... Кстати, когда я добавляю свое исправление для внутреннего разделения, оно работает jsfiddle.net/876sscf7/5 - person Ason; 15.10.2015
comment
Ваша скрипка делает st[1].split(' --› ')[1] пустой переменной, потому что скрипт в строке 2 должен выполнять глобальное совпадение, находить все совпадения, а не останавливаться после первого совпадения. jsfiddle.net/21kd95cj - person Parfait; 16.10.2015
comment
Вау.... Теперь я это вижу... одна из моих типичных ошибок быстрого исправления.. спасибо за ваше время. - person Ason; 16.10.2015
comment
ваш код очень хорош. но в некоторых файлах .srt я вижу, что некоторые строки имеют только время без текста, и ваш код останавливается на этой строке! вы не могли бы мне помочь? jsfiddle.net/21kd95cj/4 on row 8 спасибо - person mghhgm; 24.07.2018
comment
@Parfait Огромное спасибо ❤️❤️❤️ - person mghhgm; 27.07.2018
comment
@Parfait У меня проблема: когда в некоторых строках больше двух предложений, этот код обнаруживает только первое предложение. Например, jsfiddle.net/5v7wz4bq/3 на row 3 у нас есть 3 предложения и по результату показывать только первое предложение. вы не могли бы мне помочь? - person mghhgm; 03.08.2018
comment
@Parfait Думаю, я решил это. Пожалуйста, проверьте это: jsfiddle.net/5v7wz4bq/5 Я изменил только /(\d+)\n([\d:,]+)\s+-{2}\>\s+([\d:,]+)\n([\s\S]*?(?=\n{2}|=\n{2}))/gm Спасибо. - person mghhgm; 03.08.2018

Вот одна проблема:

o = strip(st[1].split(' --> ')[1]);

В этой строке, когда нет ' --> ' для разделения, возвращаемая длина массива равна 1, что приводит к ошибкам при запросе элемента массива 2.

А вот еще:

subtitles[cont].number = n;
....

Ни subtitles, ни его свойства .number, ... и т. д. не объявлены.

Обновить

Вот пример, который работает (переключил часть jQuery "read srt file" для данных)

var data = document.getElementById("data").innerHTML;
data = data.replace(/&gt;/g,">");

function strip(s) {
    return s.replace(/^\s+|\s+$/g,"");
}
srt = data.replace(/\r\n|\r|\n/g, '\n');
srt = strip(srt);
var srt_ = srt.split('\n\n');
var cont = 0;
var subtitles = [];

for(s in srt_) {
    st = srt_[s].split('\n');
    if(st.length >=2) {

        var st2 = st[1].split(' --> ');
        var t = st[2];

        if(st.length > 2) {
            for(j=3; j < st.length;j++)
                t += '\n'+st[j];
        }
        
        subtitles[cont] = { number : st[0],
                            start : st2[0],
                            end : st2[1],
                            text : t
                          }
        
        console.log(subtitles[cont].number + ": " + subtitles[cont].text);
        document.body.innerHTML += subtitles[cont].number + ": " + subtitles[cont].text + "<br>";
        cont++;
    }
}
<div id="data" style="display:none">1
00:00:01,000 --> 00:00:04,000
Descargados de www.AllSubs.org

2
00:00:49,581 --> 00:00:52,049
Bueno, tienes que escapar, tengo que ir a jugar

3
00:00:52,084 --> 00:00:55,178
Tengo que encontrar un día que está lleno de nada más que sol

4
00:00:55,220 --> 00:00:57,552
Crucero por la calle, moviéndose al compás

5
00:00:57,589 --> 00:01:00,683
Todos los que conoces está teniendo nada más que diversión

6
00:01:00,726 --> 00:01:03,251
Deja todo detrás de ti

7
00:01:03,295 --> 00:01:06,128
Siente esas palmeras soplan

8
00:01:06,165 --> 00:01:09,157
La gente en el norte no puede encontrar

9
00:01:09,201 --> 00:01:11,829
Están fuera de palear la nieve

10
00:01:11,870 --> 00:01:14,998
El tiempo para moverse, pero no seas lento

11
00:01:15,040 --> 00:01:17,941
En sus marcas, prepárate para ir
</div>

person Ason    schedule 15.10.2015

Лучше использовать следующее регулярное выражение, чтобы покрыть их, если количество строк текста в каждом разделе увеличивается.

/(\d+)\n([\d:,]+)\s+-{2}\>\s+([\d:,]+)\n([\s\S]*?(?=\n{2}|$))/g

Просмотрите вывод в консоли

let subtitle = document.getElementById('subtitle').value;
console.log(_subtitle(subtitle));

function _subtitle(text) {

        let Subtitle = text;
        let Pattern = /(\d+)\n([\d:,]+)\s+-{2}\>\s+([\d:,]+)\n([\s\S]*?(?=\n{2}|$))/g;
        let _regExp = new RegExp(Pattern);
        let result = [];

        if (typeof (text) != "string") throw "Sorry, Parser accept string only.";
        if (Subtitle === null) return Subtitle;

        let Parse = Subtitle.replace(/\r\n|\r|\n/g, '\n');
        let Matches;

        while ((Matches = Pattern.exec(Parse)) != null) {

result.push({
                Line: Matches[1],
                Start: Matches[2],
                End: Matches[3],
                Text: Matches[4],
            })

        }
        
        return result;

    }
<textarea id="subtitle">1
00:00:00,000 --> 00:00:00,600
Hi my friends

2
00:00:00,610 --> 00:00:01,050
In the first line, everything works properly
But there is a problem in the second line that I could not solve :(

3
00:00:01,080 --> 00:00:03,080
But then everything is in order and good

4
00:00:03,280 --> 00:00:05,280
You do me a great favor by helping me. Thankful</textarea>

person Mohammad Shateri    schedule 06.12.2020