-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathvdscript_to_llc.py
More file actions
192 lines (164 loc) · 8.65 KB
/
vdscript_to_llc.py
File metadata and controls
192 lines (164 loc) · 8.65 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
import re
import json
import os
# ----------------------------------------------------------------------
# Script: vdscript_to_llc.py
# Description:
# This script converts VirtualDub or VirtualDub2 .vdscript files into
# LosslessCut .llc files.
# WARNING: NOT FRAME ACCURATE! (Hence the "extra_frames_x" parameters).
# This script was tested and works with:
# - Python 3.13.2
# - VirtualDub2 (build 44282) .vdscript files
# - LosslessCut 3.65.0
#
# Features:
# - Convert VirtualDub(.vdscript) cuts into LosslessCut(.llc) format.
# - Option to add or remove frames at the beginning and/or end of each cut.
# - Ensures no negative frame values (e.g., if a cut starts at frame 0).
# - Prevents segments from having a non-positive duration after adjustments.
# - Option to automatically add segment numbers to the "name" field of
# each cut (e.g., "segment 1", "segment 2", etc.).
#
# Note:
# - The `extra_frames_start` and `extra_frames_end` parameters can now accept
# negative values to remove frames from the start or end of each segment.
# - If a negative value for `extra_frames_start` causes the start frame to go
# below 0, the script will adjust the start frame to 0.
# - If the adjusted end frame becomes less than or equal to the adjusted start
# frame (resulting in a non-positive duration), the script will skip that segment
# and issue a warning.
# - When using negative values, care must be taken to ensure that segments remain valid.
# - ABOUT THE "extra_frames_end" FEATURE:
# The "extra_frames_end" feature will not cause any problems if the
# frames are added at the very end of your input video (if your last
# segment's end point is at the very last frame of the input video).
# LosslessCut will display that there are extra frames, but when that
# last segment is saved, its end point will be exactly the same as
# if there were no extra frames added to that end point at all!
# - It's important to know that for both "extra_frames_start" &
# "extra_frames_end", positive values always ADD frames, & negative
# values always REMOVE frames from your segments!
#
# Usage:
# 1. Place this script in the same directory as your .vdscript file or specify
# the full path to your .vdscript file in the `vdscript_filepath` variable.
# 2. Edit the script parameters in the "Usage example" section:
# - `vdscript_filepath`: Path to your .vdscript file.
# - `llc_filepath`: Desired path for the output .llc file.
# - `media_filename`: Name of the original video file.
# - `fps`: Frame rate of your video (e.g., 23.976, 25).
# CHECK AND SET THE FRAME RATE TO MATCH THE VIDEO BEING USED!!
# This is particularly important since the script's accuracy depends on it!
# - `extra_frames_start`: Frames to add/remove at the beginning of each cut (can be negative).
# - `extra_frames_end`: Frames to add/remove at the end of each cut (can be negative).
# - `add_segment_number`: Set this to True to add numbering (e.g., "segment 1").
# 3. Run the script.
# ----------------------------------------------------------------------
# Function to convert frame number to time in seconds
def frames_to_timecode(frames, fps):
"""
Converts a frame number to a timecode in seconds.
Args:
frames (int): The frame number.
fps (float): The frame rate of the video.
Returns:
float: The timecode in seconds, rounded to 3 decimal places.
"""
return round(frames / fps, 3)
# Function to parse the .vdscript file and adjust frames for each cut
def parse_vdscript(filepath, fps, extra_frames_start, extra_frames_end, add_segment_number=False):
"""
Parses the .vdscript file to extract cut ranges and convert them into timecodes.
Args:
filepath (str): Path to the .vdscript file.
fps (float): Frame rate of the video.
extra_frames_start (int): Number of frames to add/remove at the start of each cut (can be negative).
extra_frames_end (int): Number of frames to add/remove at the end of each cut (can be negative).
add_segment_number (bool): Whether to add segment numbers in the "name" field.
Returns:
list: A list of dictionaries representing cut segments with start and end times.
"""
cut_segments = []
with open(filepath, 'r') as file:
lines = file.readlines()
# Regex to match VirtualDub subset lines (e.g., VirtualDub.subset.AddRange(412,208);)
subset_pattern = re.compile(r'VirtualDub\.subset\.AddRange\((\d+),(\d+)\);')
segment_number = 1 # Initialize the segment counter
for line in lines:
match = subset_pattern.match(line)
if match:
start_frame = int(match.group(1))
frame_count = int(match.group(2))
# Adjust the start frame
new_start_frame = start_frame - extra_frames_start
# Ensure start frame is not negative
new_start_frame = max(new_start_frame, 0)
# Adjust the end frame
new_end_frame = start_frame + frame_count + extra_frames_end
# Ensure end frame is greater than start frame
if new_end_frame <= new_start_frame:
print(f"Warning: Segment {segment_number} has non-positive duration after adjusting frames. Skipping this segment.")
segment_number += 1
continue
# Convert frames to time
start_time = frames_to_timecode(new_start_frame, fps)
end_time = frames_to_timecode(new_end_frame, fps)
# Name the segment with the segment number if requested
segment_name = f"segment {segment_number}" if add_segment_number else ""
# Append the segment to the list
cut_segments.append({
"start": start_time,
"end": end_time,
"name": segment_name
})
segment_number += 1 # Increment the segment number
return cut_segments
# Function to write the LosslessCut .llc file
def write_llc_file(output_filepath, media_filename, cut_segments):
"""
Writes the cut segments to a LosslessCut .llc file in JSON format.
Args:
output_filepath (str): Path to save the .llc file.
media_filename (str): Name of the original media file.
cut_segments (list): List of dictionaries representing cut segments.
"""
if os.path.exists(output_filepath):
print(f"Error: The file {output_filepath} already exists. Please choose a different filename or remove the existing file.")
return
llc_data = {
"version": 1,
"mediaFileName": media_filename,
"cutSegments": cut_segments
}
with open(output_filepath, 'w') as file:
json.dump(llc_data, file, indent=2)
print(f"LosslessCut file saved as {output_filepath}")
# Main function to perform the conversion
def convert_vdscript_to_llc(vdscript_filepath, llc_filepath, media_filename, fps, extra_frames_start, extra_frames_end, add_segment_number=False):
"""
Main function to convert a .vdscript file to a .llc file for LosslessCut.
Args:
vdscript_filepath (str): Path to the .vdscript file.
llc_filepath (str): Path to save the .llc file.
media_filename (str): Name of the original media file.
fps (float): Frame rate of the video.
extra_frames_start (int): Number of frames to add/remove at the start of each cut (can be negative).
extra_frames_end (int): Number of frames to add/remove at the end of each cut (can be negative).
add_segment_number (bool): Whether to add segment numbers in the "name" field.
"""
cut_segments = parse_vdscript(vdscript_filepath, fps, extra_frames_start, extra_frames_end, add_segment_number)
if cut_segments:
write_llc_file(llc_filepath, media_filename, cut_segments)
else:
print("No valid segments to write to the LosslessCut file.")
# Usage example - EDIT THESE VALUES
if __name__ == "__main__":
vdscript_filepath = r"C:\New folder\test.vdscript" # Path to the .vdscript file
llc_filepath = r"C:\New folder\output.llc" # Path to save the .llc file
media_filename = "test.mp4" # Name of the video file
fps = ? # Frame rate of the video - Replace '?' with the correct value (e.g., 23.976, 25)
extra_frames_start = 0 # Number of frames to add/remove at the start of each cut (can be negative)
extra_frames_end = 0 # Number of frames to add/remove at the end of each cut (can be negative)
add_segment_number = False # Set to True to add segment numbers in the "name" field
convert_vdscript_to_llc(vdscript_filepath, llc_filepath, media_filename, fps, extra_frames_start, extra_frames_end, add_segment_number)