Advertisement
Guest User

Untitled

a guest
Oct 2nd, 2023
7
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.15 KB | None | 0 0
  1. # ##### BEGIN GPL LICENSE BLOCK #####
  2. #
  3. # This program is free software; you can redistribute it and/or
  4. # modify it under the terms of the GNU General Public License
  5. # as published by the Free Software Foundation; either version 2
  6. # of the License, or (at your option) any later version.
  7. #
  8. # This program is distributed in the hope that it will be useful,
  9. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. # GNU General Public License for more details.
  12. #
  13. # You should have received a copy of the GNU General Public License
  14. # along with this program; if not, write to the Free Software Foundation,
  15. # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  16. #
  17. # ##### END GPL LICENSE BLOCK #####
  18.  
  19. bl_info = {
  20. "name": "Add Rendered Strips",
  21. "author": "tintwotin",
  22. "version": (1, 0),
  23. "blender": (3, 4, 0),
  24. "location": "Add > Rendered Strips",
  25. "description": "Render selected strips to hard disk and add the rendered files as movie strips to the original scene in the first free channel",
  26. "warning": "",
  27. "doc_url": "",
  28. "category": "Sequencer",
  29. }
  30.  
  31. import os
  32. import bpy
  33. from datetime import date
  34.  
  35.  
  36. def find_first_empty_channel(start_frame, end_frame):
  37. for ch in range(1, len(bpy.context.scene.sequence_editor.sequences_all) + 1):
  38. for seq in bpy.context.scene.sequence_editor.sequences_all:
  39. if (
  40. seq.channel == ch
  41. and seq.frame_final_start < end_frame
  42. and (seq.frame_final_start + seq.frame_final_duration) > start_frame
  43. ):
  44. break
  45. else:
  46. return ch
  47. return 1
  48.  
  49.  
  50. class RenderSelectedStripsOperator(bpy.types.Operator):
  51. """Render selected strips to hard disk and add the rendered files as movie strips to the original scene in the first free channel"""
  52.  
  53. bl_idname = "sequencer.render_selected_strips"
  54. bl_label = "Rendered Strips"
  55. bl_options = {"REGISTER", "UNDO"}
  56.  
  57. @classmethod
  58. def poll(cls, context):
  59. return context and context.scene and context.scene.sequence_editor
  60.  
  61. def execute(self, context):
  62. # Check for the context and selected strips
  63. if not context or not context.scene or not context.scene.sequence_editor:
  64. self.report({"ERROR"}, "No valid context or selected strips")
  65. return {"CANCELLED"}
  66.  
  67. # Get the current scene and sequencer
  68. current_scene = context.scene
  69. sequencer = current_scene.sequence_editor
  70. current_frame_old = bpy.context.scene.frame_current
  71.  
  72. # Check if there are any selected strips
  73. if not any(strip.select for strip in sequencer.sequences_all):
  74. self.report({"ERROR"}, "No strips selected")
  75. return {"CANCELLED"}
  76.  
  77. # Get the selected sequences in the sequencer
  78. selected_sequences = bpy.context.selected_sequences
  79.  
  80. # Get the first empty channel above all strips
  81. insert_channel_total = 1
  82. for s in sequencer.sequences_all:
  83. if s.channel >= insert_channel_total:
  84. insert_channel_total = s.channel + 1
  85.  
  86. # Loop over the selected strips in the current scene
  87. for strip in selected_sequences:
  88. if strip.type in {"MOVIE", "IMAGE", "SOUND", "SCENE", "TEXT", "COLOR", "META", "MASK"}:
  89.  
  90. # Deselect all strips in the current scene
  91. for s in sequencer.sequences_all:
  92. s.select = False
  93.  
  94. # Select the current strip in the current scene
  95. strip.select = True
  96.  
  97. # Store current frame for later
  98. bpy.context.scene.frame_current = int(strip.frame_start)
  99.  
  100. # Copy the strip to the clipboard
  101. bpy.ops.sequencer.copy()
  102.  
  103. # Create a new scene
  104. #new_scene = bpy.data.scenes.new(name="New Scene")
  105.  
  106. # Create a new scene
  107. new_scene = bpy.ops.scene.new(type='EMPTY')
  108.  
  109. # Get the newly created scene
  110. new_scene = bpy.context.scene
  111.  
  112. # Add a sequencer to the new scene
  113. new_scene.sequence_editor_create()
  114.  
  115. # Set the new scene as the active scene
  116. context.window.scene = new_scene
  117.  
  118. # Copy the scene properties from the current scene to the new scene
  119. new_scene.render.resolution_x = current_scene.render.resolution_x
  120. new_scene.render.resolution_y = current_scene.render.resolution_y
  121. new_scene.render.resolution_percentage = (current_scene.render.resolution_percentage)
  122. new_scene.render.pixel_aspect_x = current_scene.render.pixel_aspect_x
  123. new_scene.render.pixel_aspect_y = current_scene.render.pixel_aspect_y
  124. new_scene.render.fps = current_scene.render.fps
  125. new_scene.render.fps_base = current_scene.render.fps_base
  126. new_scene.render.sequencer_gl_preview = (current_scene.render.sequencer_gl_preview)
  127. new_scene.render.use_sequencer_override_scene_strip = (current_scene.render.use_sequencer_override_scene_strip)
  128. new_scene.world = current_scene.world
  129.  
  130. area = [area for area in context.screen.areas if area.type == "SEQUENCE_EDITOR"][0]
  131.  
  132. with bpy.context.temp_override(area=area):
  133.  
  134. # Paste the strip from the clipboard to the new scene
  135. bpy.ops.sequencer.paste()
  136.  
  137. # Get the new strip in the new scene
  138. new_strip = (new_scene.sequence_editor.active_strip) = bpy.context.selected_sequences[0]
  139.  
  140. # Set the range in the new scene to fit the pasted strip
  141. new_scene.frame_start = int(new_strip.frame_final_start)
  142. new_scene.frame_end = (int(new_strip.frame_final_start + new_strip.frame_final_duration)-1)
  143.  
  144. # Set the name of the file
  145. src_name = strip.name
  146. src_dir = ""
  147. src_ext = ".mp4"
  148.  
  149. # Set the path to the blend file
  150. blend_path = bpy.data.filepath
  151. if blend_path:
  152. rendered_dir = bpy.path.abspath(os.path.dirname(blend_path)) + "/strips"
  153. else:
  154. rendered_dir = bpy.path.abspath(os.path.expanduser("~")) + "/strips"
  155.  
  156. # Set the render settings for rendering animation with FFmpeg and MP4 with sound
  157. bpy.context.scene.render.image_settings.file_format = "FFMPEG"
  158. bpy.context.scene.render.ffmpeg.format = "MPEG4"
  159. bpy.context.scene.render.ffmpeg.audio_codec = "AAC"
  160.  
  161. # Create a new folder for the rendered files
  162. if not os.path.exists(rendered_dir):
  163. os.makedirs(rendered_dir)
  164.  
  165. # Set the output path for the rendering
  166. output_path = os.path.join(
  167. rendered_dir, src_name + "_rendered" + src_ext
  168. )
  169. new_scene.render.filepath = output_path
  170.  
  171. # Render the strip to hard disk
  172. bpy.ops.render.opengl(animation=True, sequencer=True)
  173.  
  174. # Delete the new scene
  175. bpy.data.scenes.remove(new_scene, do_unlink=True)
  176.  
  177. # Set the original scene as the active scene
  178. context.window.scene = current_scene
  179.  
  180. # Reset to total top channel
  181. insert_channel = insert_channel_total
  182.  
  183. area = [area for area in context.screen.areas if area.type == "SEQUENCE_EDITOR"][0]
  184.  
  185. with bpy.context.temp_override(area=area):
  186.  
  187. insert_channel = find_first_empty_channel(strip.frame_final_start, strip.frame_final_start+strip.frame_final_duration)
  188.  
  189. if strip.type == "SOUND":
  190. # Insert the rendered file as a sound strip in the original scene without video.
  191. bpy.ops.sequencer.sound_strip_add(
  192. channel=insert_channel,
  193. filepath=output_path,
  194. frame_start=int(strip.frame_final_start),
  195. overlap=0,
  196. )
  197. elif strip.type == "SCENE":
  198. # Insert the rendered file as a movie strip and sound strip in the original scene.
  199. bpy.ops.sequencer.movie_strip_add(
  200. channel=insert_channel,
  201. filepath=output_path,
  202. sound=False,
  203. frame_start=int(strip.frame_final_start),
  204. overlap=0,
  205. )
  206. else:
  207. # Insert the rendered file as a movie strip in the original scene without sound.
  208. bpy.ops.sequencer.movie_strip_add(
  209. channel=insert_channel,
  210. filepath=output_path,
  211. frame_start=int(strip.frame_final_start),
  212. overlap=0,
  213. sound=False,
  214. )
  215.  
  216. # Redraw UI to display the new strip. Remove this if Blender crashes: https://docs.blender.org/api/current/info_gotcha.html#can-i-redraw-during-script-execution
  217. bpy.ops.wm.redraw_timer(type="DRAW_WIN_SWAP", iterations=1)
  218.  
  219. # Reset current frame
  220. bpy.context.scene.frame_current = current_frame_old
  221. return {"FINISHED"}
  222.  
  223.  
  224. def menu_func(self, context):
  225. self.layout.separator()
  226. self.layout.operator(RenderSelectedStripsOperator.bl_idname, icon="SEQ_STRIP_DUPLICATE")
  227.  
  228.  
  229. def register():
  230. bpy.utils.register_class(RenderSelectedStripsOperator)
  231. bpy.types.SEQUENCER_MT_add.append(menu_func)
  232.  
  233.  
  234. def unregister():
  235. bpy.types.SEQUENCER_MT_strip.remove(menu_func)
  236. bpy.utils.unregister_class(RenderSelectedStripsOperator)
  237.  
  238.  
  239. if __name__ == "__main__":
  240. register()
  241.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement