import bpy
from pathlib import Path
from datetime import datetime
import math
class BlenderVideoEditor:
def __init__(self):
'''initialize start_frame and duration of video-synced-audio'''
self.vsa="/media/amit/4CFC-8D04/DCIM/1"
self.start_n_dur=list()
self.mask_images = list()
def get_video_file_names(self, dir="/media/amit/4CFC-8D04/DCIM/1"):
p = Path(dir)
return [x.absolute() for x in sorted(p.iterdir()) if not x.is_dir()]
def add_movie_clips_from(self, dir="/media/amit/4CFC-8D04/DCIM/2", start_frame=1, channel=2):
frame_s = start_frame
for i, x in enumerate(self.get_video_file_names(dir=dir)):
clip_v = bpy.context.scene.sequence_editor.sequences.new_movie(name=str(i),filepath=str(x),channel=channel, frame_start = frame_s)
clip_a = bpy.context.scene.sequence_editor.sequences.new_sound(name=str(i),filepath=str(x),channel=channel+1, frame_start = frame_s)
dur = max([clip_v.frame_duration, clip_a.frame_duration])
self.start_n_dur.append((frame_s, dur))
frame_s = frame_s + dur
def add_dependent_movie_clip(self, dir="/media/amit/4CFC-8D04/DCIM/1", start_frame=1, channel=1):
assert len(self.start_n_dur) > 0
try:
for i, x in enumerate(self.get_video_file_names(dir=dir)):
clip_v = bpy.context.scene.sequence_editor.sequences.new_movie(name=str(i), filepath=str(x), channel=channel, frame_start=self.start_n_dur[i][0])
clip_v.frame_final_duration = self.start_n_dur[i][1]
except Exception as e:
print(e)
def transform_overlay_video(self, channel=3):
'''Ensure that the overlay video is positioned at near top right corner'''
for strip in bpy.data.scenes["Scene"].sequence_editor.sequences_all:
if strip.channel == channel:
assert strip.type == "MOVIE"
strip.transform.offset_x = 440
strip.transform.offset_y = 260
strip.transform.scale_x = 0.8
strip.transform.scale_y = 0.8
def mute_sequence(movieSequence=None, mute=True):
'''Mute a supplied movie sequence'''
if None != movieSequence:
movieSequence.mute = mute
def create_mask(self, file="", for_moviesequence=None):
# name for a new image that would be used as a mask
time_string = datetime.now().strftime("%f")
mask_image = None
if len(self.mask_images) == 0:
mask_image = bpy.data.scenes["Scene"].sequence_editor.sequences.new_image(name=time_string, filepath=file, channel=4, frame_start=1)
self.mask_images.append(mask_image)
if None != for_moviesequence:
mask_image.frame_final_duration = for_moviesequence.frame_duration
else:
mask_image = self.mask_images[-1]
for_moviesequence.modifiers.new(name="circle", type="MASK")
if None != mask_image:
for_moviesequence.modifiers["circle"].input_mask_strip = mask_image
def rotate_moviesequences_by_180(self):
for seq in bpy.data.scenes["Scene"].sequence_editor.sequences:
if 'MOVIE' == seq.type:
seq.transform.rotation = math.pi
def render(self):
bpy.context.scene.render.resolution_percentage = 100
bpy.context.scene.render.use_file_extension = True
bpy.context.scene.render.image_settings.file_format = 'FFMPEG'
bpy.context.scene.render.ffmpeg.format = 'MPEG4'
bpy.context.scene.render.fps = 24
bpy.context.scene.render.use_overwrite = True
bpy.context.scene.render.filepath = '/home/amit/Downloads/final_timelapse.mp4'
bpy.context.scene.frame_start = 1
bpy.context.scene.frame_end = 239326
step = 14
for frame in range(bpy.context.scene.frame_start, bpy.context.scene.frame_end + 1, step):
bpy.context.scene.frame_set(frame)
bpy.ops.render.render(write_still=False)
def add_mask_to_all_in_channel(self, channel=2, mask_file="/home/amit/Documents/pendrive/Career-Template/7-podcasts-blender/3-dashcam-template/masks/0.png"):
mask_image_file = mask_file
for seq in bpy.data.scenes["Scene"].sequence_editor.sequences:
if 'MOVIE' == seq.type and channel == seq.channel:
self.create_mask(file=mask_image_file, for_moviesequence=seq)
def mute_all_in_channel(self, channel=3):
for seq in bpy.data.scenes["Scene"].sequence_editor.sequences:
if channel==seq.channel:
seq.mute = True
def add_text_strip(self, file="///home/amit/Documents/pendrive/Career-Template/7-podcasts-blender/2-personal-youtube-channel/Diplomatic-Dispatch-Series-Sansad-Tv/LabelTrack.txt", fps=30):
'''Add text strip to the video sequence'''
path=file
p = Path(path)
lines = list()
with open(p, "r", encoding='utf-8-sig') as f:
lines = f.readlines()
ts = None
for l in lines:
la = l.split("\t")
fs = (int(float(la[0].strip())) + 1) * fps
fe = ((int(float(la[1].strip())) + 1) * fps ) + 3
self.add_banner_at(y=-375, w=1.5, h=0.2, start_f=fs, dur=fe-fs, text=l.split("\t")[2].strip())
#ts = bpy.context.scene.sequence_editor.sequences.new_effect(name="subtitle", type="TEXT", channel=6, frame_start = fs, frame_end = fe)
#ts.text = l.split("\t")[2].strip()
#ts.transform.offset_y=-444
#ts.font_size = 42
def add_banner_at(self, font_size=42 ,start_f=1, x=0, y=0, w=1, h=0.1, text="", dur=64826, channel=5, banner_color=(0, 0.5, 0.5), text_color=(1, 1, 1, 1)):
'''Add a banner with text'''
frame_s = start_f
timestring = datetime.now().strftime("%f")
color_clip = bpy.context.scene.sequence_editor.sequences.new_effect(name="color"+timestring, type="COLOR", channel = channel+2, frame_start = frame_s, frame_end = frame_s + 240)
color_clip.color = banner_color
color_clip.blend_type = 'ALPHA_OVER'
color_clip.blend_alpha = 0.5
color_clip.transform.scale_y = h
color_clip.transform.scale_x = w
color_clip.transform.offset_y = y
color_clip.transform.offset_x = x
subtitle_clip = bpy.context.scene.sequence_editor.sequences.new_effect(name="subtitle"+timestring, type="TEXT", channel = channel+3, frame_start = frame_s, frame_end = frame_s + 240)
# subtitle_clip.text = str(x[1]) + " UTC; " + str(self.readExif(filename=str(x[0])))
subtitle_clip.text = text
subtitle_clip.color = text_color
subtitle_clip.transform.offset_y= y
subtitle_clip.transform.offset_x= x
subtitle_clip.font_size = font_size
color_clip.frame_final_duration = dur
subtitle_clip.frame_final_duration = dur
def add_image(self, file=""):
'''add image in the sequence editor'''
timestring = datetime.now().strftime("%f")
img = bpy.context.scene.sequence_editor.sequences.new_image(name=timestring, filepath=file, channel=16, frame_start=3646)
img.frame_final_duration = 1827
def process(self):
# self.add_movie_clips_from(dir="/media/amit/AKS-MEL-DSS")
#self.add_banner_at(text="CICD+'Repository Management' in one Application", y=-180, font_size=24, dur=1280, channel=10, text_color=(1, 0.12, 0.33, 1))
# self.add_banner_at(text="CICD+'Repository Management' in one Application", y=-500, font_size=42, dur=1280, channel=10, text_color=(1, 0.12, 0.33, 1))
#self.add_banner_at(text="Master of Engineering Leadership at UBC, Vancouver in 2018", start_f=1 , y=-500, font_size=42, dur=68093, channel=5, text_color=(1, 1, 0, 1))
# self.add_banner_at(x=-500,y=130,w=0.4,h=0.2,text="Traditional Agile", start_f=2128 , font_size=42, dur=3345, channel=11, text_color=(1, 0.12, 0.33, 1))
#self.add_image(file="/home/amit/Documents/pendrive/Career-Template/7-podcasts-blender/0-workbench/2-Site-Reliability-Engineering-In-IT-Consulting/media/images/SRE-DevOps.png")
self.add_text_strip(file="/media/amit/AKS-MEL-DSS/LabelTrack.txt")
if __name__ == '__main__':
bve = BlenderVideoEditor()
bve.process()
Created
April 25, 2023 21:52
-
-
Save aksinghdce/ce8b648f2bc078e418d7f17f727eb753 to your computer and use it in GitHub Desktop.
Code to generate video with subtitles using Audacity, Python and Blender
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment