Я перекодировал, чтобы полагаться на пакет pysrt
, как было запрошено, и символ re
.
Идея состоит в том, чтобы создать словарь на основе start_times.
Есливремя начала существует, данные добавляются к записи за это время, но время окончания обновляется в то же время, поэтому время окончания увеличивается с текстом.
Если время начала не существует, это просто новый словарьзапись.
Время начала продвигается только тогда, когда мы знаем, что предложение закончено.
Итак, по сути, мы начинаем строить предложение с фиксированным временем начала.Предложение продолжает строиться, добавляя больше текста и обновляя время окончания, пока предложение не закончится.Здесь мы увеличиваем время начала, используя текущую запись, которую мы знаем как новое предложение.
Записи подзаголовка с несколькими предложениями разбиты, при этом время начала и окончания вычисляется с использованием записи pysrt
character_per_second
для всей записи подзаголовка до ее разбивки.
Наконец, новый файл подзаголовка записывается на диск из записей в словаре.
Очевидно, что, имея только один файл для воспроизведения, я вполне могу пропустить некоторые препятствия макета подзаголовка на дороге, но, по крайней мере, это даст вам рабочую отправную точку.
Код прокомментирован повсюду, поэтому большинство вещей должно быть понятно, как и почему.
Редактировать: я уточнил проверку на наличие времени начала словаря и изменил метод, используемый для определения, закончилось ли предложение, т.е.после разбиения полный текст возвращается к тексту.
Второе упомянутое вами видео имеет субтитры, которые для начала немного смещены, обратите внимание, что миллисекундных значений нет вообще.
Следующий код отлично справляется со вторым видео и хорошо справляется с первым.
Редактировать 2: добавлены смежные точки и удаление тегов html <>
Редактировать 3: получается, что pysrt
удаляет теги html из расчета для символов в секунду.Теперь я также сделал это, что означает, что форматирование <html>
может быть сохранено в подзаголовках.
Редактировать 4: Эта версия справляется с полными остановками в математических и химических формулах, плюс числа ip и т. Д. В основном места, где полный останов не означает полную остановку.Это также позволяет предложения, которые заканчиваются?и!
import pysrt
import re
abbreviations = ['Dr.','Mr.','Mrs.','Ms.','etc.','Jr.','e.g.'] # You get the idea!
abbrev_replace = ['Dr','Mr','Mrs','Ms','etc','Jr','eg']
subs = pysrt.open('new.srt')
subs_dict = {} # Dictionary to accumulate new sub-titles (start_time:[end_time,sentence])
start_sentence = True # Toggle this at the start and end of sentences
# regex to remove html tags from the character count
tags = re.compile(r'<.*?>')
# regex to split on ".", "?" or "!" ONLY if it is preceded by something else
# which is not a digit and is not a space. (Not perfect but close enough)
# Note: ? and ! can be an issue in some languages (e.g. french) where both ? and !
# are traditionally preceded by a space ! rather than!
end_of_sentence = re.compile(r'([^\s\0-9][\.\?\!])')
# End of sentence characters
eos_chars = set([".","?","!"])
for sub in subs:
if start_sentence:
start_time = sub.start
start_sentence = False
text = sub.text
#Remove multiple full-stops e.g. "and ....."
text = re.sub('\.+', '.', text)
# Optional
for idx, abr in enumerate(abbreviations):
if abr in text:
text = text.replace(abr,abbrev_replace[idx])
# A test could also be made for initials in names i.e. John E. Rotten - showing my age there ;)
multi = re.split(end_of_sentence,text.strip())
cps = sub.characters_per_second
# Test for a sub-title with multiple sentences
if len(multi) > 1:
# regex end_of_sentence breaks sentence start and sentence end into 2 parts
# we need to put them back together again.
# hence the odd range because the joined end part is then deleted
for cnt in range(divmod(len(multi),2)[0]): # e.g. len=3 give 0 | 5 gives 0,1 | 7 gives 0,1,2
multi[cnt] = multi[cnt] + multi[cnt+1]
del multi[cnt+1]
for part in multi:
if len(part): # Avoid blank parts
pass
else:
continue
# Convert start time to seconds
h,m,s,milli = re.split(':|,',str(start_time))
s_time = (3600*int(h))+(60*int(m))+int(s)+(int(milli)/1000)
# test for existing data
try:
existing_data = subs_dict[str(start_time)]
end_time = str(existing_data[0])
h,m,s,milli = re.split(':|,',str(existing_data[0]))
e_time = (3600*int(h))+(60*int(m))+int(s)+(int(milli)/1000)
except:
existing_data = []
e_time = s_time
# End time is the start time or existing end time + the time taken to say the current words
# based on the calculated number of characters per second
# use regex "tags" to remove any html tags from the character count.
e_time = e_time + len(tags.sub('',part)) / cps
# Convert start to a timestamp
s,milli = divmod(s_time,1)
m,s = divmod(int(s),60)
h,m = divmod(m,60)
start_time = "{:02d}:{:02d}:{:02d},{:03d}".format(h,m,s,round(milli*1000))
# Convert end to a timestamp
s,milli = divmod(e_time,1)
m,s = divmod(int(s),60)
h,m = divmod(m,60)
end_time = "{:02d}:{:02d}:{:02d},{:03d}".format(h,m,s,round(milli*1000))
# if text already exists add the current text to the existing text
# if not use the current text to write/rewrite the dictionary entry
if existing_data:
new_text = existing_data[1] + " " + part
else:
new_text = part
subs_dict[str(start_time)] = [end_time,new_text]
# if sentence ends re-set the current start time to the end time just calculated
if any(x in eos_chars for x in part):
start_sentence = True
start_time = end_time
print ("Split",start_time,"-->",end_time,)
print (new_text)
print('\n')
else:
start_sentence = False
else: # This is Not a multi-part sub-title
end_time = str(sub.end)
# Check for an existing dictionary entry for this start time
try:
existing_data = subs_dict[str(start_time)]
except:
existing_data = []
# if it already exists add the current text to the existing text
# if not use the current text
if existing_data:
new_text = existing_data[1] + " " + text
else:
new_text = text
# Create or Update the dictionary entry for this start time
# with the updated text and the current end time
subs_dict[str(start_time)] = [end_time,new_text]
if any(x in eos_chars for x in text):
start_sentence = True
print ("Single",start_time,"-->",end_time,)
print (new_text)
print('\n')
else:
start_sentence = False
# Generate the new sub-title file from the dictionary
idx=0
outfile = open('video_new.srt','w')
for key, text in subs_dict.items():
idx+=1
outfile.write(str(idx)+"\n")
outfile.write(key+" --> "+text[0]+"\n")
outfile.write(text[1]+"\n\n")
outfile.close()
Вывод после прохождения вышеуказанного кода для вашего video.srt
файла выглядит следующим образом:
1
00:00:13,100 --> 00:00:27,280
Dr Martin Luther King, Jr, in a 1968 speech where he reflects
upon the Civil Rights Movement, states, "In the end, we will remember not the words of our enemies but the silence of our friends."
2
00:00:27,280 --> 00:00:29,800
As a teacher, I've internalized this message.
3
00:00:29,800 --> 00:00:39,701
Every day, all around us, we see the consequences of silence manifest themselves in the form of discrimination, violence, genocide and war.
4
00:00:39,701 --> 00:00:46,178
In the classroom, I challenge my students to explore the silences in their own lives through poetry.
5
00:00:46,178 --> 00:00:54,740
We work together to fill those spaces, to recognize them, to name them, to understand that they don't
have to be sources of shame.
6
00:00:54,740 --> 00:01:14,408
In an effort to create a culture within my classroom where students feel safe sharing the intimacies of their own silences, I have four core principles posted on the board that sits in the front of my class, which every student signs
at the beginning of the year: read critically, write consciously, speak clearly, tell your truth.
7
00:01:14,408 --> 00:01:18,871
And I find myself thinking a lot about that last point, tell your truth.
8
00:01:18,871 --> 00:01:28,848
And I realized that if I was going to ask my students to speak up, I was going to have to tell my truth and be honest with them about the times where I failed to do so.
9
00:01:28,848 --> 00:01:44,479
So I tell them that growing up, as a kid in a Catholic family in New Orleans, during Lent I was always taught that the most meaningful thing one could do was to give something up, sacrifice something you typically indulge in to prove to God you understand his sanctity.
10
00:01:44,479 --> 00:01:50,183
I've given up soda, McDonald's, French fries, French kisses, and everything in between.
11
00:01:50,183 --> 00:01:54,071
But one year, I gave up speaking.
12
00:01:54,071 --> 00:02:03,286
I figured the most valuable thing I could sacrifice was my own voice, but it was like I hadn't realized that I had given that up a long time ago.
13
00:02:03,286 --> 00:02:23,167
I spent so much of my life telling people the things they wanted to hear instead of the things they needed to, told myself I wasn't meant to be anyone's conscience because I still had to figure out being my own, so sometimes I just wouldn't say anything, appeasing ignorance with my silence, unaware that validation doesn't need words to endorse its existence.
14
00:02:23,167 --> 00:02:29,000
When Christian was beat up for being gay, I put my hands in my pocket and walked with my head
down as if I didn't even notice.
15
00:02:29,000 --> 00:02:39,502
I couldn't use my locker for weeks
because the bolt on the lock reminded me of the one I had put on my lips when the homeless man on the corner looked at me with eyes up merely searching for an affirmation that he was worth seeing.
16
00:02:39,502 --> 00:02:43,170
I was more concerned with
touching the screen on my Apple than actually feeding him one.
17
00:02:43,170 --> 00:02:46,049
When the woman at the fundraising gala said "I'm so proud of you.
18
00:02:46,049 --> 00:02:53,699
It must be so hard teaching
those poor, unintelligent kids," I bit my lip, because apparently
we needed her money more than my students needed their dignity.
19
00:02:53,699 --> 00:03:02,878
We spend so much time listening to the things people are saying that we rarely pay attention to the things they don't.
20
00:03:02,878 --> 00:03:06,139
Silence is the residue of fear.
21
00:03:06,139 --> 00:03:09,615
It is feeling your flaws gut-wrench guillotine your tongue.
22
00:03:09,615 --> 00:03:13,429
It is the air retreating from your chest because it doesn't feel safe in your lungs.
23
00:03:13,429 --> 00:03:15,186
Silence is Rwandan genocide.
24
00:03:15,186 --> 00:03:16,423
Silence is Katrina.
25
00:03:16,553 --> 00:03:19,661
It is what you hear when there
aren't enough body bags left.
26
00:03:19,661 --> 00:03:22,062
It is the sound after the noose is already tied.
27
00:03:22,062 --> 00:03:22,870
It is charring.
28
00:03:22,870 --> 00:03:23,620
It is chains.
29
00:03:23,620 --> 00:03:24,543
It is privilege.
30
00:03:24,543 --> 00:03:25,178
It is pain.
31
00:03:25,409 --> 00:03:28,897
There is no time to pick your battles when your battles have already picked you.
32
00:03:28,897 --> 00:03:31,960
I will not let silence wrap itself around my indecision.
33
00:03:31,960 --> 00:03:36,287
I will tell Christian that he is a lion, a sanctuary of bravery and brilliance.
34
00:03:36,287 --> 00:03:42,340
I will ask that homeless man what his name is and how his day was, because sometimes all people want to be is human.
35
00:03:42,340 --> 00:03:51,665
I will tell that woman that my students can talk about transcendentalism like their last name was Thoreau, and just because you watched
one episode of "The Wire" doesn't mean you know anything about my kids.
36
00:03:51,665 --> 00:04:03,825
So this year, instead of giving something up, I will live every day as if there were a microphone tucked under my tongue, a stage on the underside of my inhibition.
37
00:04:03,825 --> 00:04:10,207
Because who has to have a soapbox when all you've ever needed is your voice?
38
00:04:10,207 --> 00:04:12,712
Thank you.
39
00:04:12,712 --> 00:00:00,000
(Applause)