2013-11-20 7 views
1

Я работаю над этим эскизом на обработке, которая получает видеофайлы с моей веб-камеры/смартфона и показывает его при запуске. Я хочу импортировать .srt, преобразованный в файл субтитров txt из фильма к нему. Я вижу, что текстовый файл имеет все эти номера, которые обозначают начало и конец кадра субтитров перед фактическим текстом.Импорт субтитров в обработке

Вот пример:

{9232}{9331}Those swings are dangerous.|Stay off there. I haven't fixed them yet. 
{9333}{9374}I think you're gonna live. 

То, что я хотел бы сделать, это понять ута код, который будет

  1. использовать цифры и установить их в качестве начала/конца кадра для запуска справа время, как в пленке
  2. отображение субтитров
  3. выяснить, как знак «|» можно использовать в качестве символа для запуска в сценарии изменения строки.

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

Я предполагаю, что я хочу сделать, это спасти меня от этого весь

if ((current_frame > 9232) && ((current_frame < 9331)) { 
    text("Those swings are dangerous.", 200, 500/2); 
    text("Stay off there. I haven't fixed them yet..", 200, (500/2 + 35)); 
} 

вещь для каждого субтитра ...

Я совершенно новой для обработки, так не то, что знакомы со многими командами, помимо «для» и «если», новичок в импорте .txt файлы и невеждой в W orking с массивами. Но я действительно хочу, чтобы найти хороший способ в последние два бита ..

Любая помощь в любой форме будет весьма признателен :)

Приветствия, Джордж

ответ

2

Для отображения соответствующие субтитры, вы могли бы сделать что-то вроде следующего (объяснение ниже, извините заранее за стену текста):

String[] subtitles = loadStrings("subtitles.txt"); 
int currentFrame = 0; 
int subtitleIndex = -1; 
int startFrame = -1, endFrame = -1; 
int fontSize = 10; //change to suit your taste 
String[] currentSubtitle; 
... 

//draw loop start: 
//video drawing code goes here 

if(currentFrame > endFrame){ //update which subtitle is now/next 
    subtitleIndex++; 
    startFrame = int(subtitles[subtitleIndex].split("\\}\\{")[0].substring(1)); 
    endFrame = int(subtitles[subtitleIndex].split("\\}\\{")[1].split("\\}")[0]); 
    currentSubtitle = subtitles[subtitleIndex].split("\\}")[2].split("\\|"); 
} 
if(currentFrame >= startFrame && currentFrame <= endFrame){ 
    for(int i = 0; i < currentSubtitle.length; i++){ 
    text(currentSubtitle[i], width/2, height - fontSize * (currentSubtitle.length - i)); 
    } 
} 
currentFrame++; 
//draw loop end 

Вероятно, что выглядит довольно устрашающе к вам, так вот некоторые проходных комментарии. Ваша программа будет иметь тип state machine. Он будет либо находиться в состоянии отображения субтитров, либо нет. Мы будем помнить это позже, когда мы разрабатываем код. Во-первых, вам нужно объявить и инициализировать свои переменные.

В первой строке используется функция loadStrings(), которая считывает текстовый файл и возвращает массив String, где каждый элемент массива является строкой в ​​файле. Конечно, вам нужно будет изменить имя файла в соответствии с вашим файлом.

Ваш код использует переменную с именем current_frame, что очень хорошая идея, но я переименовал ее в currentFrame, чтобы соответствовать стандарту java-кодирования. Мы начнем с нуля, а позже наш код увеличит его на каждом дисплее кадра. Эта переменная сообщит нам, где мы находимся в последовательности субтитров и какое сообщение должно отображаться (если есть).

Поскольку информация для какого кадра начинается и заканчивается каждый субтитр, закодирована в строке, немного сложно включить его в код. Пока же давайте просто создадим некоторые переменные, которые представляют, когда «текущие» субтитры - субтитры, которые мы сейчас показываем или будем показывать далее, начинаются и заканчиваются.Мы также создадим индекс, чтобы отслеживать, какой элемент в массиве subtitles является «текущим» субтитрами. Все эти переменные начинаются с -1, что может показаться немного странным. В то время как мы инициализировали currentFrame до 0, они действительно не имеют реального «начального» значения, по крайней мере, пока. Если мы выбрали 0, то это не так, потому что первый субтитр не может (возможно, нет) начинаться и заканчиваться в кадре 0, а любое другое положительное число не имеет большого смысла. -1 часто используется в качестве фиктивного индекса, который будет заменен до того, как переменная фактически будет использоваться, поэтому мы тоже это сделаем.

Теперь для конечной переменной: currentSubtitle. Непосредственная мысль заключалась в том, чтобы это было просто String, а не массив String. Однако, поскольку каждый субтитр может быть разделен на символы (|), каждый субтитр может фактически представлять несколько строк текста, поэтому мы создадим массив, чтобы быть в безопасности. Возможно, что некоторые субтитры могут быть одноэлементным массивом, но это нормально.

Теперь для тяжелой части!

Предположительно, ваш код будет иметь какой-то цикл в нем, где на каждой итерации соответствующий видеокадр обращается к экрану и (если условия выполняются), субтитры нарисованы поверх него. Я оставил часть видео, так как это не часть вашего вопроса.

Прежде чем мы сделаем что-нибудь еще, нам нужно помнить, что некоторые из наших переменных еще не имеют реальных значений - все эти -1 s от прежде чем нужно что-то установить. Основная логика цикла рисования: 1) выяснить, нужно ли подзаголовок рисовать, и если да, нарисуйте его и 2) выясните, нужно ли «текущий» субтитр перемещаться в следующий массив. Давайте сначала будем делать # 2, потому что в первый раз через цикл мы ничего об этом не знаем! Критерий (в общем) для перехода к следующему подзаголовку - это если мы закончили текущий текущий: currentFrame > endFrame. Если это так, нам нужно перенести все наши переменные в следующий подзаголовок. subtitleIndex легко, мы просто добавим один и все. Остальные ... не так просто. Я знаю, что это выглядит отвратительно, но я расскажу об этом в конце, чтобы не нарушить поток. Пропустите вперед, если вы просто не можете ждать :)

После (при необходимости) изменения всех переменных, чтобы они соответствовали текущему субтитрам, нам нужно сделать фактическое отображение. Второй оператор if проверяет, не «внутри» границ фрейма текущего субтитров. Поскольку переменная currentSubtitle может ссылаться на субтитры, которые должны отображаться справа или просто просто в следующем порядке, нам нужно сделать некоторую проверку, чтобы определить, какой из них для этого кадра. Это второй оператор if - если мы закончили старт и до конца, тогда мы должны отображать субтитры! Напомним, что наша переменная currentSubtitle является массивом, поэтому мы не можем просто отображать ее напрямую. Нам нужно будет пройти через него и отобразить каждый элемент на отдельной строке. Вы упомянули команду text(), поэтому я не буду углубляться здесь. Трудным битом является y-координата текста, так как предполагается, что он находится на нескольких строках. Мы хотим, чтобы первый элемент был выше второго, который выше третьего и т. Д. Для этого мы будем зависеть от y-координаты от того, на каком элементе мы находимся, с пометкой i. Мы можем масштабировать разницу между строками, изменив значение fontSize; это будет только на ваш вкус. Знайте, что номер, который вы установили для него, будет равен высоте строки в пикселях.

Теперь для грязного бита, который я не хотел объяснять выше. Этот код зависит от метода Stringsplit(), который выполняется для строки, которую вы хотите разделить, и берет строку в качестве параметра, который инструктирует ее как разбить строку: a regex.Чтобы получить startFrame из строки субтитров в файле, нам нужно разбить его по фигурным скобкам, потому что это разделители между числами. Во-первых, мы будем разбивать строку везде, где «} {« происходит »сразу после первого числа (и прямо перед вторым). Поскольку split() возвращает массив, мы можем ссылаться на него на одну строку, используя индекс между квадратными скобками. Мы знаем, что первое число будет в первом возврате строки, разделив на "} {", поэтому мы будем использовать индекс 0. Это вернет (например) «{1234», потому что split() удаляет вещь, на которую вы делите. Теперь нам нужно просто взять substring, который происходит после первого символа, преобразовать его в int с помощью int(), и все готово!

Для второго номера мы можем использовать аналогичный подход. Давайте разделить на "} {" снова, только мы возьмем второй элемент (индекс 1) в возвращаемом массиве на этот раз. Теперь у нас есть что-то вроде «9331». Эти качели - это dang ... », которые мы можем снова разбить на«} », выбрать первую строку этого массива, преобразовать в int, и все готово! В обоих случаях мы используем subtitles[subtitleIndex] в качестве исходной строки, которая представляет исходный ввод файла, который мы загрузили с использованием loadStrings() в начале. Обратите внимание, что во время всего этого разделения исходная строка в subtitles никогда не изменяется - split(), substring() и т. Д. Возвращают только новые последовательности и не изменяют строку, на которую вы ее называли.

Я оставлю вас, чтобы выяснить, как последняя строка в этой последовательности работает :)

Наконец, вы увидите, что есть куча обратных слэшей захламления split() звонков. Это связано с тем, что split() занимает регулярное выражение, а не просто строку. Regexs используют множество специальных обозначений, которые я не буду здесь вводить, но если вы только что прошли split() что-то вроде "}{", оно попытается интерпретировать его, и оно не будет вести себя так, как ожидалось. Вам нужно указать escape символов, указав split(), что вы не хотите, чтобы их интерпретировали как специальные, и вам просто нужны сами символы. Для этого вы используете обратную реакцию перед любым символом, который должен быть экранирован. Тем не менее, обратная косая черта - еще один особый характер, поэтому вам тоже нужно избегать этого! Это приводит к таким вещам, как "\\{" - первая обратная косая черта ускользает от второй, которая ускользает от третьего символа. Обратите внимание, что символ | также должен быть экранирован.

Извините за стену текста! Приятно видеть разумные и вежливые вопросы, поэтому я подумал, что дам хороший ответ в ответ.

+0

Фантастический ответ! – mdomino

Смежные вопросы