This repository has been archived by the owner on Jul 6, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
96f925f
commit a91db70
Showing
10 changed files
with
328 additions
and
23 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,3 +4,4 @@ dist/ | |
__pycache__/ | ||
debug.json | ||
*.mp4 | ||
*.png |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,2 @@ | ||
from .main import convert_video | ||
from .preview import * |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
from .main import convert_image_from_frame |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
from typing import Optional | ||
|
||
from style import Order | ||
from vsml import SourceContent, VSMLContent, WrapContent | ||
|
||
|
||
def pick_data( | ||
vsml_content: VSMLContent, second: float | ||
) -> Optional[VSMLContent]: | ||
if not vsml_content.exist_video: | ||
return None | ||
if isinstance(vsml_content, WrapContent): | ||
if vsml_content.style.order == Order.SEQUENCE: | ||
items = vsml_content.items | ||
vsml_content.items = [] | ||
whole_second = 0 | ||
left_margin_end = 0 | ||
|
||
for item in items: | ||
whole_second += max( | ||
item.style.time_margin_start.get_second(), left_margin_end | ||
) | ||
if second < whole_second: | ||
return vsml_content | ||
whole_second += item.style.time_padding_start.get_second() | ||
if second < whole_second: | ||
item._second = -1 | ||
vsml_content.items = [item] | ||
return vsml_content | ||
whole_second_with_object_length = ( | ||
whole_second + item.style.object_length.get_second() | ||
) | ||
if second < whole_second_with_object_length: | ||
child = pick_data(item, second - whole_second) | ||
if child is not None: | ||
vsml_content.items = [child] | ||
return vsml_content | ||
whole_second = whole_second_with_object_length | ||
whole_second += item.style.time_padding_end.get_second() | ||
if second < whole_second: | ||
item._second = -1 | ||
vsml_content.items = [item] | ||
return vsml_content | ||
left_margin_end = item.style.time_margin_end.get_second() | ||
|
||
elif vsml_content.style.order == Order.PARALLEL: | ||
items = vsml_content.items | ||
vsml_content.items = [] | ||
|
||
for item in items: | ||
whole_second = item.style.time_margin_start.get_second() | ||
if second < whole_second: | ||
continue | ||
whole_second += item.style.time_padding_start.get_second() | ||
if second < whole_second: | ||
item._second = -1 | ||
vsml_content.items.append(item) | ||
continue | ||
whole_second_with_object_length = ( | ||
whole_second + item.style.object_length.get_second() | ||
) | ||
if ( | ||
second < whole_second_with_object_length | ||
or item.style.object_length.is_fit() | ||
): | ||
child = pick_data(item, second - whole_second) | ||
if child is not None: | ||
vsml_content.items.append(child) | ||
continue | ||
whole_second = whole_second_with_object_length | ||
whole_second += item.style.time_padding_end.get_second() | ||
if second < whole_second: | ||
item._second = -1 | ||
vsml_content.items.append(item) | ||
continue | ||
return vsml_content | ||
|
||
else: | ||
raise Exception() | ||
elif isinstance(vsml_content, SourceContent): | ||
vsml_content._second = second | ||
return vsml_content | ||
else: | ||
raise Exception() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
from typing import Optional | ||
|
||
import ffmpeg | ||
|
||
from converter.ffmpeg import set_background_filter | ||
from utils import VSMLManager | ||
from vsml import VSML, WrapContent | ||
|
||
from .content import pick_data | ||
from .process import create_preview_process | ||
|
||
|
||
def convert_image_from_frame( | ||
vsml_data: VSML, frame: int, output_path: Optional[str] | ||
) -> None: | ||
output_path = "preview.png" if output_path is None else output_path | ||
second = frame / VSMLManager.get_root_fps() | ||
if second > vsml_data.content.style.object_length.get_second(): | ||
raise Exception() | ||
vsml_content_for_pick = None | ||
vsml_content = vsml_data.content | ||
if second >= vsml_content.style.time_margin_start.get_second(): | ||
if second < vsml_content.style.time_padding_start.get_second(): | ||
if isinstance(vsml_content, WrapContent): | ||
vsml_content.items = [] | ||
vsml_content_for_pick = vsml_content | ||
else: | ||
vsml_content_for_pick = pick_data(vsml_content, second) | ||
|
||
process = create_preview_process(vsml_content_for_pick) | ||
process.video = set_background_filter( | ||
background_color=vsml_content.style.background_color, | ||
resolution_text=VSMLManager.get_root_resolution().get_str(), | ||
video_process=process.video, | ||
fit_video_process=True, | ||
) | ||
process = ffmpeg.output(process.video, output_path, vframes=1) | ||
process.run(overwrite_output=True) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,164 @@ | ||
from typing import Optional | ||
|
||
import ffmpeg | ||
|
||
from converter.ffmpeg import ( | ||
get_background_process, | ||
get_source_process, | ||
get_text_process, | ||
layering_filter, | ||
set_background_filter, | ||
width_height_filter, | ||
) | ||
from converter.schemas import Process | ||
from style import GraphicValue, LayerMode, Order | ||
from utils import SourceType | ||
from vsml import SourceContent, VSMLContent, WrapContent | ||
|
||
|
||
def create_preview_source_process(vsml_content: SourceContent) -> Process: | ||
style = vsml_content.style | ||
if vsml_content.type == SourceType.TEXT: | ||
video_process = get_text_process( | ||
vsml_content.src_path, | ||
style.get_width_with_padding(), | ||
style.get_height_with_padding(), | ||
style.padding_left, | ||
style.padding_top, | ||
style.background_color, | ||
style.using_font_path, | ||
style.font_size, | ||
style.font_color, | ||
style.font_border_color, | ||
style.font_border_width, | ||
) | ||
else: | ||
video_process = get_source_process( | ||
vsml_content.src_path, | ||
exist_video=True, | ||
exist_audio=False, | ||
)["video"] | ||
if vsml_content.type != SourceType.TEXT: | ||
video_process = width_height_filter( | ||
style.width, style.height, video_process | ||
) | ||
if ( | ||
style.padding_top.is_zero_over() | ||
or style.padding_left.is_zero_over() | ||
): | ||
video_process = set_background_filter( | ||
width=style.get_width_with_padding(), | ||
height=style.get_height_with_padding(), | ||
background_color=style.background_color, | ||
video_process=video_process, | ||
position_x=style.padding_left, | ||
position_y=style.padding_top, | ||
fit_video_process=True, | ||
) | ||
if vsml_content._second != -1 and vsml_content.tag_name == "vid": | ||
video_process = ffmpeg.trim(video_process, start=vsml_content._second) | ||
return Process(video_process, None, vsml_content.style) | ||
|
||
|
||
def create_preview_wrap_process( | ||
child_processes: list[Process], vsml_content: WrapContent | ||
) -> Process: | ||
style = vsml_content.style | ||
video_process = None | ||
width = style.get_width_with_padding() | ||
height = style.get_height_with_padding() | ||
if style.order == Order.SEQUENCE: | ||
if len(child_processes): | ||
video_process = child_processes[0].video | ||
else: | ||
video_process = get_background_process( | ||
"{}x{}".format( | ||
width.get_pixel(), | ||
height.get_pixel(), | ||
), | ||
style.background_color, | ||
) | ||
|
||
elif style.order == Order.PARALLEL: | ||
video_process = get_background_process( | ||
"{}x{}".format( | ||
width.get_pixel(), | ||
height.get_pixel(), | ||
), | ||
style.background_color, | ||
) | ||
is_single = style.layer_mode == LayerMode.SINGLE | ||
is_row = style.direction is None or style.direction.is_row() | ||
is_reverse = style.direction is None or style.direction.is_reverse | ||
current_graphic_length = ( | ||
( | ||
width - style.padding_right | ||
if is_row | ||
else height - style.padding_bottom | ||
) | ||
if is_reverse | ||
else (style.padding_left if is_row else style.padding_top) | ||
) | ||
remain_margin = GraphicValue("0") | ||
|
||
for child_process in child_processes: | ||
child_style = child_process.style | ||
if child_process.video is not None: | ||
max_space = max( | ||
( | ||
child_style.margin_left | ||
if is_row | ||
else child_style.margin_top | ||
), | ||
remain_margin, | ||
) | ||
child_graphic_length = ( | ||
child_style.get_width_with_padding() | ||
if is_row | ||
else child_style.get_height_with_padding() | ||
) | ||
|
||
current_graphic_length += ( | ||
-child_graphic_length if is_reverse else max_space | ||
) | ||
video_process = layering_filter( | ||
video_process, | ||
child_process.video, | ||
( | ||
current_graphic_length | ||
if is_single and is_row | ||
else style.padding_left + child_style.margin_left | ||
), | ||
( | ||
current_graphic_length | ||
if is_single and not is_row | ||
else style.padding_top + child_style.margin_top | ||
), | ||
) | ||
current_graphic_length += ( | ||
-max_space if is_reverse else child_graphic_length | ||
) | ||
remain_margin = ( | ||
child_style.margin_right | ||
if is_row | ||
else child_style.margin_bottom | ||
) | ||
else: | ||
raise Exception() | ||
return Process(video_process, None, style) | ||
|
||
|
||
def create_preview_process(vsml_content: Optional[VSMLContent]) -> Process: | ||
if isinstance(vsml_content, SourceContent): | ||
process = create_preview_source_process(vsml_content) | ||
elif isinstance(vsml_content, WrapContent): | ||
child_processes = [] | ||
for item in vsml_content.items: | ||
child_process = create_preview_process(item) | ||
if child_process is not None: | ||
child_processes.append(child_process) | ||
process = create_preview_wrap_process(child_processes, vsml_content) | ||
else: | ||
raise Exception() | ||
|
||
return process |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters