in experiments/veo-app/pages/portraits.py [0:0]
def motion_portraits_content(app_state: me.state):
"""Motion portraits Mesop Page"""
state = me.state(PageState)
with page_scaffold(): # pylint: disable=not-context-manager
with page_frame(): # pylint: disable=not-context-manager
header("Motion Portraits", "portrait")
with me.box(
style=me.Style(
display="flex",
flex_direction="row",
gap=20,
)
):
# Uploaded image
with me.box(style=_BOX_STYLE_CENTER_DISTRIBUTED):
me.text("Portrait")
if state.reference_image_uri:
output_url = state.reference_image_uri
print(f"Displaying reference image: {output_url}")
me.image(
src=output_url,
style=me.Style(
height=200, border_radius=12, object_fit="contain"
),
key=str(state.reference_image_file_key),
)
else:
# me.image(src=None, style=me.Style(height=200))
me.box(
style=me.Style(
height=200,
width=200,
display="flex",
align_items="center",
justify_content="center",
background=me.theme_var(
"sys-color-surface-container-highest"
),
border_radius=12,
border=me.Border.all(
me.BorderSide(
color=me.theme_var("sys-color-outline")
)
),
)
)
# uploader controls
with me.box(
style=me.Style(
display="flex",
flex_direction="row",
gap=10,
margin=me.Margin(top=10),
)
):
# me.button(label="Upload", type="flat", disabled=True)
me.uploader(
label="Upload",
accepted_file_types=["image/jpeg", "image/png"],
on_upload=on_click_upload,
type="flat",
color="primary",
style=me.Style(font_weight="bold"),
)
me.button(
label="Clear",
on_click=on_click_clear_reference_image,
)
with me.box(
style=me.Style(
display="flex",
flex_direction="column",
gap=15,
padding=me.Padding.all(12),
flex_grow=1,
)
):
me.text(
"Video options",
style=me.Style(font_size="1.1em", font_weight="bold"),
)
with me.box(
style=me.Style(display="flex", flex_direction="row", gap=5)
):
me.select(
label="aspect",
appearance="outline",
options=[
me.SelectOption(label="16:9 widescreen", value="16:9"),
me.SelectOption(label="9:16 portrait", value="9:16"),
],
value=state.aspect_ratio,
on_selection_change=on_selection_change_aspect,
)
me.select(
label="length",
options=[
me.SelectOption(label="5 seconds", value="5"),
me.SelectOption(label="6 seconds", value="6"),
me.SelectOption(label="7 seconds", value="7"),
me.SelectOption(label="8 seconds", value="8"),
],
appearance="outline",
style=me.Style(),
value=f"{state.video_length}",
on_selection_change=on_selection_change_length,
)
me.checkbox(
label="auto-enhance prompt",
checked=state.auto_enhance_prompt,
on_change=on_change_auto_enhance_prompt,
)
me.text(
"Style options",
style=me.Style(font_size="1.1em", font_weight="bold"),
)
with me.box(
style=me.Style(display="flex", flex_direction="row", gap=5)
):
for option in modifier_options:
is_selected = option["key"] in state.modifier_array
# Use me.content_button. We'll place an icon and text inside.
with me.content_button(
key=f"mod_btn_{option['key']}",
# key=option["key"], # Crucial for identifying the button in the event handler
on_click=on_modifier_click,
# Optional: Add some styling to make the buttons look more like selectable items
style=me.Style(
padding=me.Padding.symmetric(
vertical=8, horizontal=16
),
border=me.Border.all(
me.BorderSide(
width=1,
color=me.theme_var("sys-color-primary")
if is_selected
else me.theme_var("sys-color-outline"),
)
),
background=me.theme_var(
"sys-color-primary-container"
)
if is_selected
else "transparent",
border_radius=20, # Makes it more chip-like
),
):
# Use a horizontal box to arrange icon and text
with me.box(
style=me.Style(
display="flex",
flex_direction="row",
align_items="center",
gap=6, # Space between icon and text
)
):
if is_selected:
# Display a check icon when selected
me.icon(
"check",
style=me.Style(
color=me.theme_var(
"sys-color-on-primary-container"
)
if is_selected
else me.theme_var(
"sys-color-on-surface"
)
),
)
# else:
# Optionally, a placeholder or different icon for unselected state
# For now, no icon when not selected.
# me.icon("add_circle_outline", style=me.Style(color=me.theme_var("sys-color-on-surface-variant")))
# The label for the modifier
me.text(
option["label"],
style=me.Style(
color=me.theme_var(
"sys-color-on-primary-container"
)
if is_selected
else me.theme_var("sys-color-on-surface")
),
)
if state.modifier_array:
me.text(
f"Active Modifiers: {', '.join(state.modifier_array)}",
style=me.Style(margin=me.Margin(top=10), font_size="0.9em"),
)
with me.box(
style=me.Style(
padding=me.Padding.all(16),
justify_content="center",
display="flex",
)
):
with me.content_button(
on_click=on_click_motion_portraits,
type="flat",
key="generate_motion_portrait_button",
disabled=state.is_loading or not state.reference_image_uri,
):
with me.box(
style=me.Style(
display="flex",
flex_direction="row",
align_items="center",
gap=2,
)
):
if state.is_loading:
me.progress_spinner(diameter=20, stroke_width=3)
me.text("Generating...")
else:
me.icon("portrait")
me.text("Create Moving Portrait")
me.box(style=me.Style(height=24))
# Generated video and prompt section
if (
state.is_loading
or state.result_video
or state.error_message
or state.generated_scene_direction
):
with me.box(style=_BOX_STYLE_CENTER_DISTRIBUTED_MARGIN):
if state.is_loading:
me.text(
"Generating your moving portrait, please wait...",
style=me.Style(
font_size="1.1em", margin=me.Margin(bottom=10)
),
)
me.progress_spinner(diameter=40)
elif state.result_video:
me.text(
"Motion Portrait",
style=me.Style(
font_size="1.2em",
font_weight="bold",
margin=me.Margin(bottom=10),
),
)
video_url = state.result_video.replace(
"gs://", "https://storage.mtls.cloud.google.com/"
)
print(f"Displaying result video: {video_url}")
me.video(
src=video_url,
style=me.Style(
width="100%",
max_width="480px"
if state.aspect_ratio == "9:16"
else "720px",
border_radius=12,
margin=me.Margin(top=8),
),
# autoplay=True,
# controls=True
)
if state.timing:
me.text(
state.timing,
style=me.Style(
margin=me.Margin(top=10), font_size="0.9em"
),
)
# Display generated scene direction
if state.generated_scene_direction and not state.is_loading:
me.text(
"Generated Scene Direction:",
style=me.Style(
font_size="1.1em",
font_weight="bold",
margin=me.Margin(top=15, bottom=5),
),
)
me.text(
state.generated_scene_direction,
style=me.Style(
white_space="pre-wrap",
font_family="monospace",
background=me.theme_var("sys-color-surface-container"),
padding=me.Padding.all(10),
border_radius=8,
),
)
# Display error message if any
if (
state.show_error_dialog
and state.error_message
and not state.is_loading
):
me.text(
"Error",
style=me.Style(
font_size="1.2em",
font_weight="bold",
color="red",
margin=me.Margin(top=15, bottom=5),
),
)
me.text(
state.error_message,
style=me.Style(color="red", white_space="pre-wrap"),
)