2024-05-27 14:40:23 +02:00
|
|
|
import os
|
2024-05-24 09:44:19 +02:00
|
|
|
import re
|
|
|
|
import subprocess
|
|
|
|
|
2024-05-27 14:40:23 +02:00
|
|
|
import bpy
|
2024-05-24 09:44:19 +02:00
|
|
|
|
2024-05-27 14:40:23 +02:00
|
|
|
from vse_toolbox import bl_utils
|
2024-05-24 09:44:19 +02:00
|
|
|
|
|
|
|
|
2024-05-27 14:40:23 +02:00
|
|
|
def launch_split(movie_strip, threshold, frame_start=None, frame_end=None):
|
|
|
|
"""Launch ffmpeg command to detect changing frames from a movie strip.
|
2024-05-24 09:44:19 +02:00
|
|
|
|
2024-05-27 14:40:23 +02:00
|
|
|
Args:
|
|
|
|
movie_strip (bpy.types.Sequence): blender sequence strip to detect changes.
|
|
|
|
threshold (float): value of the detection factor (from 0 to 1).
|
|
|
|
frame_start (int, optional): first frame to detect.
|
|
|
|
Defaults to None.
|
|
|
|
frame_end (int, optional): last frame to detect.
|
|
|
|
Defaults to None.
|
2024-05-24 09:44:19 +02:00
|
|
|
|
2024-05-27 14:40:23 +02:00
|
|
|
Returns:
|
|
|
|
str: ffmpeg command log.
|
|
|
|
"""
|
2024-05-24 09:44:19 +02:00
|
|
|
|
2024-05-27 14:40:23 +02:00
|
|
|
path = bl_utils.abspath(movie_strip.filepath)
|
|
|
|
fps = bpy.context.scene.render.fps
|
2024-05-24 09:44:19 +02:00
|
|
|
|
2024-05-27 14:40:23 +02:00
|
|
|
if frame_start is None:
|
2024-05-28 14:49:28 +02:00
|
|
|
frame_start = 0
|
2024-05-27 14:40:23 +02:00
|
|
|
if frame_end is None:
|
2024-05-28 14:49:28 +02:00
|
|
|
frame_end = movie_strip.frame_duration
|
2024-05-24 09:44:19 +02:00
|
|
|
|
2024-05-28 14:49:28 +02:00
|
|
|
frame_start = frame_start - movie_strip.frame_start
|
|
|
|
|
|
|
|
#frame_start += movie_strip.frame_offset_start
|
|
|
|
#frame_end -= movie_strip.frame_offset_end
|
2024-05-24 09:44:19 +02:00
|
|
|
|
2024-05-27 14:40:23 +02:00
|
|
|
# Launch ffmpeg command to split
|
|
|
|
ffmpeg_cmd = get_command(str(path), threshold, frame_start, frame_end, fps)
|
2024-05-24 09:44:19 +02:00
|
|
|
|
2024-05-27 14:40:23 +02:00
|
|
|
print(ffmpeg_cmd)
|
|
|
|
process = subprocess.Popen(
|
|
|
|
ffmpeg_cmd,
|
|
|
|
stdout=subprocess.PIPE,
|
|
|
|
stderr=subprocess.STDOUT,
|
|
|
|
universal_newlines=True)
|
2024-05-24 09:44:19 +02:00
|
|
|
|
2024-05-27 14:40:23 +02:00
|
|
|
return process
|
2024-05-24 09:44:19 +02:00
|
|
|
|
|
|
|
|
2024-05-27 14:40:23 +02:00
|
|
|
def get_command(path, threshold, frame_start, frame_end, fps):
|
|
|
|
"""Generate the ffmpeg command which detect change from a movie.
|
|
|
|
|
|
|
|
Args:
|
|
|
|
path (_type_): path to detect changes.
|
|
|
|
threshold (_type_): value of the detection factor (from 0 to 1).
|
|
|
|
frame_start (_type_): first frame to detect.
|
|
|
|
frame_end (_type_): last frame to detect.
|
|
|
|
fps (_type_): framerate of the movie.
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
list: ffmpeg command as list for subprocess module.
|
|
|
|
"""
|
|
|
|
|
|
|
|
start_time = frame_start/fps
|
|
|
|
end_time = frame_end/fps
|
|
|
|
|
|
|
|
return [
|
|
|
|
'ffmpeg',
|
|
|
|
'-i',
|
|
|
|
str(path),
|
|
|
|
'-vf',
|
|
|
|
f"trim=start={start_time}:end={end_time}, select='gt(scene, {threshold})',showinfo",
|
|
|
|
'-f',
|
|
|
|
'null',
|
|
|
|
'-'
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
def get_split_time(log, as_frame=True, fps=None):
|
|
|
|
"""Parse ffmpeg command lines to detect the timecode
|
|
|
|
|
|
|
|
Args:
|
|
|
|
log (str): log to parse.
|
|
|
|
as_frame (bool, optional): if wanted the timecode as frame number.
|
|
|
|
Defaults to True.
|
|
|
|
fps (_type_, optional): framerate of the movie (mandatory if as_frame used).
|
|
|
|
Defaults to None.
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
_type_: _description_
|
|
|
|
"""
|
|
|
|
timecodes = re.findall(r'pts_time:([\d.]+)', log)
|
|
|
|
|
|
|
|
if not timecodes:
|
|
|
|
return
|
|
|
|
|
|
|
|
timecode = timecodes[0]
|
|
|
|
|
|
|
|
if as_frame:
|
|
|
|
# convert timecode to frame number
|
|
|
|
return round(float(timecode) * fps)
|
|
|
|
|
|
|
|
return timecode
|