Advertisement
Luc_Vest

Generate Subtitles With Highlighting And Stroke (Outline)

Feb 5th, 2023
865
0
Never
1
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 3.69 KB | None | 0 0
  1. """
  2. Subtitles in moviepy are still annoying, but doable
  3.  
  4. I struggled with this, so maybe somebody else did too.  You can't use pango with stroke (stroke_width) so if you want to change one word, you're screwed. I run this on linux cuz it's easier than figuring out how to get ImageMagick working on Windows, lol
  5.  
  6. I don't do the timings manually (I'd die).  I use AWS Transcribe, and as long as it's less than 60 minutes a month, it's free for the first year.  It's cheap if you go over anyway
  7.  
  8. The video is generated with Deforum notebook (Stable Diffusion)
  9.  
  10. If you navigated here from somewhere other than my video, here's a link to see the end result
  11.  
  12. https://youtu.be/YN_XWoMTGdY
  13. """
  14.  
  15. import math
  16. from moviepy.editor import *
  17. from moviepy.video.tools import *
  18.  
  19. screensize = (1024, 768)
  20. audioclip = AudioFileClip("untitled.mp3")
  21. v4 = VideoFileClip('20230205043321.mp4')
  22. clip_list = [v4]
  23.  
  24.  
  25. def do_text(text, font_size, main_color, highlight_color, highlight_index, start_time, end_time, y_pos= 573, wobble = 1.0, backcolor = "white"):
  26.     def lambda_with_var(i, yi, w):
  27.         return lambda t: (i, yi + w * t * 10 * math.sin(t * 3 + i))
  28.     items = []
  29.     widths = [0]
  30.     te = text.split(' ')
  31.     co = [main_color] * len(te)
  32.     if highlight_index >= 0 and highlight_index < len(co):
  33.         co[highlight_index] = highlight_color
  34.  
  35.     for i in range(len(te)):
  36.  
  37.         txt_clip = TextClip(te[i], method='label', fontsize=font_size, color=co[i], stroke_color=backcolor,
  38.                             stroke_width=1.5, font='URW-Chancery-L-Medium-Italic').set_duration(end_time - start_time)
  39.         txt_clip = txt_clip.set_start(start_time)
  40.         widths.append(widths[-1] + txt_clip.size[0] + 10)
  41.         items.append(txt_clip)
  42.  
  43.     assert widths[-1] < screensize[0], f"Too damn wide! {widths[-1]}"
  44.     indent = (screensize[0] - widths[-1]) // 2
  45.     for i in range(len(items)):
  46.         items[i] = items[i].set_pos(lambda_with_var(widths[i] + indent, y_pos, wobble))
  47.  
  48.     clip_list.extend(items)
  49.  
  50.  
  51. do_text("I want to own a sword", 120, "purple", "red", 0, 0.39, 0.62)
  52. do_text("I want to own a sword", 120, "purple", "red", 1, 0.62, 1.06)
  53. do_text("I want to own a sword", 120, "purple", "red", 2, 1.06, 1.19)
  54. do_text("I want to own a sword", 120, "purple", "red", 3, 1.2, 1.44)
  55. do_text("I want to own a sword", 120, "purple", "red", 4, 1.44, 1.5)
  56. do_text("I want to own a sword", 120, "purple", "red", 5, 1.5, 2.17)
  57. do_text("But not because Andrew Tate", 90, "purple", "red", 0, 2.17, 2.36, 500)
  58. do_text("But not because Andrew Tate", 90, "purple", "red", 1, 2.36, 2.63, 500)
  59. do_text("But not because Andrew Tate", 90, "purple", "red", 2, 2.63, 2.97, 500)
  60. do_text("But not because Andrew Tate", 90, "purple", "red", 3, 2.97, 3.38, 500)
  61. do_text("But not because Andrew Tate", 90, "purple", "red", 4, 3.38, 3.7, 500)
  62. do_text("But not because Andrew Tate", 90, "purple", "red", -1, 3.7, 4.94, 500)
  63. do_text("told me that I should!", 90, "purple", "red", -1, 2.17, 3.7, 620)
  64. do_text("told me that I should!", 90, "purple", "red", 0, 3.7, 3.99, 620)
  65. do_text("told me that I should!", 90, "purple", "red", 1, 3.99, 4.14, 620)
  66. do_text("told me that I should!", 90, "purple", "red", 2, 4.14, 4.29, 620)
  67. do_text("told me that I should!", 90, "purple", "red", 3, 4.29, 4.4, 620)
  68. do_text("told me that I should!", 90, "purple", "red", 4, 4.4, 4.94, 620)
  69. do_text("Also, I think I figured", 110, "pink", "red", -1, 5.79, 8.2, 500, backcolor = "black", wobble=0)
  70. do_text("out the subtitle thing.", 110, "yellow", "red", -1, 5.79, 8.2, 620, backcolor = "black", wobble=0)
  71. final_clip = CompositeVideoClip(clip_list).set_audio(audioclip)
  72. final_clip.write_videofile("my_concatenation.mp4", fps=24, codec='libx264', threads=7)
  73.  
  74.  
  75.  
Advertisement
Comments
  • Luc_Vest
    1 year
    # text 0.17 KB | 0 0
    1. Oh ... the youtube video is not technically the final version, because I added the wobble=0 to the last two text lines .. that was SUPPOSED to be on, but I just forgot, okay?
Add Comment
Please, Sign In to add comment
Advertisement