split.py 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. import re
  2. import difflib
  3. import math
  4. def sentence_time_ratio(text,maxLen):
  5. total_len = len(text)
  6. if total_len > maxLen:
  7. left_word = total_len % maxLen
  8. times = int(math.ceil(total_len/maxLen))
  9. if left_word < 5:
  10. times+=1
  11. sen_len = int(total_len/times)
  12. time_ratio = [None]*times
  13. sentences = [None]*times
  14. print(times,',',total_len,",",sen_len)
  15. for t in range(times):
  16. sentences[t] = text[t*sen_len:t*sen_len+sen_len]
  17. time_ratio[t] = len(sentences[t])/total_len
  18. else:
  19. time_ratio = [1]
  20. sentences = [text]
  21. return time_ratio, sentences
  22. def parse_script(file_path,gt_list):
  23. with open(file_path, 'r',encoding="utf-8") as f:
  24. raw_lines = [line.strip() for line in f]
  25. lines = adjustSub_by_text_similarity(gt_list,raw_lines)
  26. #make dict
  27. dict_list = []
  28. for idx in range(len(lines)):
  29. script={}
  30. script['content'] = lines[idx]
  31. time_raw = raw_lines[idx * 4 +1 ].split(' --> ')
  32. start = time_raw[0].split(':')
  33. stop = time_raw[1].split(':')
  34. script['start'] = float(start[0])*3600 + float(start[1])*60 + float(start[2].replace(',','.'))
  35. script['stop'] = float(stop[0])*3600 + float(stop[1])*60 + float(stop[2].replace(',','.'))
  36. dict_list.append(script)
  37. #merge duplicated sentences
  38. script_not_dup_list = []
  39. for idx in range(len(dict_list)):
  40. dup_list = []
  41. for idx_inner in range(len(dict_list)):
  42. if dict_list[idx_inner]['content']==dict_list[idx]['content']:
  43. dup_list.append(idx_inner)
  44. for dup_idx in dup_list:
  45. if dup_idx == min(dup_list):
  46. dict_list[dup_idx]['type'] = 'lead_sentence'
  47. else:
  48. dict_list[dup_idx]['type'] = 'duplicated'
  49. dict_list[dup_list[0]]['stop'] = dict_list[dup_list[-1]]['stop']
  50. if dict_list[idx]['type'] == 'lead_sentence':
  51. script_not_dup_list.append(dict_list[idx])
  52. #avoid subtitle overlapping ? Timeline overlapping not found currently
  53. #cut by max length----> eng seperated problem {eng_idx}
  54. #ENG counts, zh counts, space counts
  55. new_idx = 0
  56. splitted_dict = []
  57. for dic in dict_list:
  58. time_ratio, sentences = sentence_time_ratio(dic['content'],13)
  59. for s in range(len(sentences)):
  60. new_dict = {}
  61. new_dict['index'] = new_idx
  62. start = dic['start']
  63. for t in range(s):
  64. start += (dic['duration']*time_ratio[t])
  65. new_dict['start'] = start
  66. new_dict['duration'] = dic['duration'] * time_ratio[s]
  67. new_dict['content'] = sentences[s]
  68. new_idx+=1
  69. splitted_dict.append(new_dict)
  70. return splitted_dict
  71. def adjustSub_by_text_similarity(gts,gens_raw):
  72. gens = []
  73. for idx in range(int((len(gens_raw)+1)/4)):
  74. gens.append(gens_raw[idx*4+2])
  75. combine2 = [''.join([i,j]) for i,j in zip(gts, gts[1:])]
  76. combine3 = [''.join([i,j,k]) for i,j,k in zip(gts, gts[1:], gts[2:])]
  77. alls = gts + combine2 + combine3
  78. adjusted = [None]*len(gens)
  79. duplicated_list = []
  80. for idx in range(len(gens)):
  81. match_text = difflib.get_close_matches(gens[idx], alls, cutoff=0.1)
  82. if match_text[0] in duplicated_list:
  83. for mt in match_text:
  84. if mt == adjusted[idx-1] or mt not in duplicated_list:
  85. adjusted[idx] = mt
  86. break
  87. else:
  88. adjusted[idx] = match_text[0]
  89. duplicated_list.append(match_text[0])
  90. return adjusted
  91. def trim_punctuation(s):
  92. pat_block = u'[^\u4e00-\u9fff0-9a-zA-Z]+';
  93. pattern = u'([0-9]+{0}[0-9]+)|{0}'.format(pat_block)
  94. res = re.sub(pattern, lambda x: x.group(1) if x.group(1) else u" " ,s)
  95. return res
  96. def splitter(s):
  97. for sent in re.findall(u'[^!?,。\!\?]+[!? 。\!\?]?', s, flags=re.U):
  98. yield sent
  99. def split_by_pun(s):
  100. res = list(splitter(s))
  101. return res
  102. def split_by_word(s):
  103. slice_size = 3
  104. paragraph_len = len(s)
  105. slice_num = int(math.ceil(paragraph_len/slice_size))
  106. slice_list = []
  107. for n in range(slice_num):
  108. slice_list.append(s[n*slice_size:n*slice_size+slice_size])
  109. return slice_list
  110. raw_str = '更糟糕的是,與大量關注相伴的並非用戶讚賞,而是 Windows 10 on ARM 的不成熟暴露無遺,以及隨之而來的如潮差評──對用戶使用體驗影響最惡劣的,莫過於 Windows 10 on ARM 僅能透過模擬兼容老舊過時的 32 位元 x86 應用,而對效能與普及度俱佳的 64 位元 x86(即 x64)應用無能為力'
  111. sub_dict = parse_script("out.txt",split_by_pun(raw_str))