mirror of
https://git.datalinker.icu/comfyanonymous/ComfyUI
synced 2026-08-27 19:19:08 +08:00
fixed client bug; converted moonvalley, pika nodes
This commit is contained in:
parent
361f95b584
commit
1e00ee1073
@ -228,12 +228,13 @@ class ApiClient:
|
|||||||
form.add_field(k, str(v) if not isinstance(v, (bytes, bytearray)) else v)
|
form.add_field(k, str(v) if not isinstance(v, (bytes, bytearray)) else v)
|
||||||
|
|
||||||
if files:
|
if files:
|
||||||
for field_name, file_obj in files.items():
|
file_iter = files if isinstance(files, list) else files.items()
|
||||||
|
for field_name, file_obj in file_iter:
|
||||||
if file_obj is None:
|
if file_obj is None:
|
||||||
continue # aiohttp fails to serialize "None" values
|
continue # aiohttp fails to serialize "None" values
|
||||||
# file_obj can be (filename, bytes/io.BytesIO, content_type) tuple
|
# file_obj can be (filename, bytes/io.BytesIO, content_type) tuple
|
||||||
if isinstance(file_obj, tuple):
|
if isinstance(file_obj, tuple):
|
||||||
file_value, filename, content_type = self._unpack_tuple(file_obj)
|
filename, file_value, content_type = self._unpack_tuple(file_obj)
|
||||||
else:
|
else:
|
||||||
file_value = file_obj
|
file_value = file_obj
|
||||||
filename = getattr(file_obj, "name", field_name)
|
filename = getattr(file_obj, "name", field_name)
|
||||||
@ -313,7 +314,7 @@ class ApiClient:
|
|||||||
path: str,
|
path: str,
|
||||||
params: Optional[Dict[str, Any]] = None,
|
params: Optional[Dict[str, Any]] = None,
|
||||||
data: Optional[Dict[str, Any]] = None,
|
data: Optional[Dict[str, Any]] = None,
|
||||||
files: Optional[Dict[str, Any]] = None,
|
files: Optional[Dict[str, Any] | list[tuple[str, Any]]] = None,
|
||||||
headers: Optional[Dict[str, str]] = None,
|
headers: Optional[Dict[str, str]] = None,
|
||||||
content_type: str = "application/json",
|
content_type: str = "application/json",
|
||||||
multipart_parser: Callable | None = None,
|
multipart_parser: Callable | None = None,
|
||||||
@ -607,13 +608,13 @@ class ApiClient:
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _unpack_tuple(t):
|
def _unpack_tuple(t):
|
||||||
"""Helper to normalise (file, filename, content_type) tuples."""
|
"""Helper to normalise (filename, file, content_type) tuples."""
|
||||||
if len(t) == 3:
|
if len(t) == 3:
|
||||||
return t
|
return t
|
||||||
elif len(t) == 2:
|
elif len(t) == 2:
|
||||||
return t[0], t[1], "application/octet-stream"
|
return t[0], t[1], "application/octet-stream"
|
||||||
else:
|
else:
|
||||||
raise ValueError("files tuple must be (file, filename[, content_type])")
|
raise ValueError("files tuple must be (filename, file[, content_type])")
|
||||||
|
|
||||||
async def _get_session(self) -> aiohttp.ClientSession:
|
async def _get_session(self) -> aiohttp.ClientSession:
|
||||||
if self._session is None or self._session.closed:
|
if self._session is None or self._session.closed:
|
||||||
@ -668,7 +669,7 @@ class SynchronousOperation(Generic[T, R]):
|
|||||||
self,
|
self,
|
||||||
endpoint: ApiEndpoint[T, R],
|
endpoint: ApiEndpoint[T, R],
|
||||||
request: T,
|
request: T,
|
||||||
files: Optional[Dict[str, Any]] = None,
|
files: Optional[Dict[str, Any] | list[tuple[str, Any]]] = None,
|
||||||
api_base: str | None = None,
|
api_base: str | None = None,
|
||||||
auth_token: Optional[str] = None,
|
auth_token: Optional[str] = None,
|
||||||
comfy_api_key: Optional[str] = None,
|
comfy_api_key: Optional[str] = None,
|
||||||
|
|||||||
@ -95,14 +95,14 @@ def get_video_url_from_response(response) -> Optional[str]:
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def poll_until_finished(
|
async def poll_until_finished(
|
||||||
auth_kwargs: dict[str, str],
|
auth_kwargs: dict[str, str],
|
||||||
api_endpoint: ApiEndpoint[Any, R],
|
api_endpoint: ApiEndpoint[Any, R],
|
||||||
result_url_extractor: Optional[Callable[[R], str]] = None,
|
result_url_extractor: Optional[Callable[[R], str]] = None,
|
||||||
node_id: Optional[str] = None,
|
node_id: Optional[str] = None,
|
||||||
) -> R:
|
) -> R:
|
||||||
"""Polls the Moonvalley API endpoint until the task reaches a terminal state, then returns the response."""
|
"""Polls the Moonvalley API endpoint until the task reaches a terminal state, then returns the response."""
|
||||||
return PollingOperation(
|
return await PollingOperation(
|
||||||
poll_endpoint=api_endpoint,
|
poll_endpoint=api_endpoint,
|
||||||
completed_statuses=[
|
completed_statuses=[
|
||||||
"completed",
|
"completed",
|
||||||
@ -394,10 +394,10 @@ class BaseMoonvalleyVideoNode:
|
|||||||
else:
|
else:
|
||||||
return control_map["Motion Transfer"]
|
return control_map["Motion Transfer"]
|
||||||
|
|
||||||
def get_response(
|
async def get_response(
|
||||||
self, task_id: str, auth_kwargs: dict[str, str], node_id: Optional[str] = None
|
self, task_id: str, auth_kwargs: dict[str, str], node_id: Optional[str] = None
|
||||||
) -> MoonvalleyPromptResponse:
|
) -> MoonvalleyPromptResponse:
|
||||||
return poll_until_finished(
|
return await poll_until_finished(
|
||||||
auth_kwargs,
|
auth_kwargs,
|
||||||
ApiEndpoint(
|
ApiEndpoint(
|
||||||
path=f"{API_PROMPTS_ENDPOINT}/{task_id}",
|
path=f"{API_PROMPTS_ENDPOINT}/{task_id}",
|
||||||
@ -507,7 +507,7 @@ class MoonvalleyImg2VideoNode(BaseMoonvalleyVideoNode):
|
|||||||
RETURN_NAMES = ("video",)
|
RETURN_NAMES = ("video",)
|
||||||
DESCRIPTION = "Moonvalley Marey Image to Video Node"
|
DESCRIPTION = "Moonvalley Marey Image to Video Node"
|
||||||
|
|
||||||
def generate(
|
async def generate(
|
||||||
self, prompt, negative_prompt, unique_id: Optional[str] = None, **kwargs
|
self, prompt, negative_prompt, unique_id: Optional[str] = None, **kwargs
|
||||||
):
|
):
|
||||||
image = kwargs.get("image", None)
|
image = kwargs.get("image", None)
|
||||||
@ -532,9 +532,9 @@ class MoonvalleyImg2VideoNode(BaseMoonvalleyVideoNode):
|
|||||||
# Get MIME type from tensor - assuming PNG format for image tensors
|
# Get MIME type from tensor - assuming PNG format for image tensors
|
||||||
mime_type = "image/png"
|
mime_type = "image/png"
|
||||||
|
|
||||||
image_url = upload_images_to_comfyapi(
|
image_url = (await upload_images_to_comfyapi(
|
||||||
image, max_images=1, auth_kwargs=kwargs, mime_type=mime_type
|
image, max_images=1, auth_kwargs=kwargs, mime_type=mime_type
|
||||||
)[0]
|
))[0]
|
||||||
|
|
||||||
request = MoonvalleyTextToVideoRequest(
|
request = MoonvalleyTextToVideoRequest(
|
||||||
image_url=image_url, prompt_text=prompt, inference_params=inference_params
|
image_url=image_url, prompt_text=prompt, inference_params=inference_params
|
||||||
@ -549,14 +549,14 @@ class MoonvalleyImg2VideoNode(BaseMoonvalleyVideoNode):
|
|||||||
request=request,
|
request=request,
|
||||||
auth_kwargs=kwargs,
|
auth_kwargs=kwargs,
|
||||||
)
|
)
|
||||||
task_creation_response = initial_operation.execute()
|
task_creation_response = await initial_operation.execute()
|
||||||
validate_task_creation_response(task_creation_response)
|
validate_task_creation_response(task_creation_response)
|
||||||
task_id = task_creation_response.id
|
task_id = task_creation_response.id
|
||||||
|
|
||||||
final_response = self.get_response(
|
final_response = await self.get_response(
|
||||||
task_id, auth_kwargs=kwargs, node_id=unique_id
|
task_id, auth_kwargs=kwargs, node_id=unique_id
|
||||||
)
|
)
|
||||||
video = download_url_to_video_output(final_response.output_url)
|
video = await download_url_to_video_output(final_response.output_url)
|
||||||
return (video,)
|
return (video,)
|
||||||
|
|
||||||
|
|
||||||
@ -609,7 +609,7 @@ class MoonvalleyVideo2VideoNode(BaseMoonvalleyVideoNode):
|
|||||||
RETURN_TYPES = ("VIDEO",)
|
RETURN_TYPES = ("VIDEO",)
|
||||||
RETURN_NAMES = ("video",)
|
RETURN_NAMES = ("video",)
|
||||||
|
|
||||||
def generate(
|
async def generate(
|
||||||
self, prompt, negative_prompt, unique_id: Optional[str] = None, **kwargs
|
self, prompt, negative_prompt, unique_id: Optional[str] = None, **kwargs
|
||||||
):
|
):
|
||||||
video = kwargs.get("video")
|
video = kwargs.get("video")
|
||||||
@ -620,7 +620,7 @@ class MoonvalleyVideo2VideoNode(BaseMoonvalleyVideoNode):
|
|||||||
video_url = ""
|
video_url = ""
|
||||||
if video:
|
if video:
|
||||||
validated_video = validate_video_to_video_input(video)
|
validated_video = validate_video_to_video_input(video)
|
||||||
video_url = upload_video_to_comfyapi(validated_video, auth_kwargs=kwargs)
|
video_url = await upload_video_to_comfyapi(validated_video, auth_kwargs=kwargs)
|
||||||
|
|
||||||
control_type = kwargs.get("control_type")
|
control_type = kwargs.get("control_type")
|
||||||
motion_intensity = kwargs.get("motion_intensity")
|
motion_intensity = kwargs.get("motion_intensity")
|
||||||
@ -658,15 +658,15 @@ class MoonvalleyVideo2VideoNode(BaseMoonvalleyVideoNode):
|
|||||||
request=request,
|
request=request,
|
||||||
auth_kwargs=kwargs,
|
auth_kwargs=kwargs,
|
||||||
)
|
)
|
||||||
task_creation_response = initial_operation.execute()
|
task_creation_response = await initial_operation.execute()
|
||||||
validate_task_creation_response(task_creation_response)
|
validate_task_creation_response(task_creation_response)
|
||||||
task_id = task_creation_response.id
|
task_id = task_creation_response.id
|
||||||
|
|
||||||
final_response = self.get_response(
|
final_response = await self.get_response(
|
||||||
task_id, auth_kwargs=kwargs, node_id=unique_id
|
task_id, auth_kwargs=kwargs, node_id=unique_id
|
||||||
)
|
)
|
||||||
|
|
||||||
video = download_url_to_video_output(final_response.output_url)
|
video = await download_url_to_video_output(final_response.output_url)
|
||||||
|
|
||||||
return (video,)
|
return (video,)
|
||||||
|
|
||||||
@ -688,7 +688,7 @@ class MoonvalleyTxt2VideoNode(BaseMoonvalleyVideoNode):
|
|||||||
del input_types["optional"][param]
|
del input_types["optional"][param]
|
||||||
return input_types
|
return input_types
|
||||||
|
|
||||||
def generate(
|
async def generate(
|
||||||
self, prompt, negative_prompt, unique_id: Optional[str] = None, **kwargs
|
self, prompt, negative_prompt, unique_id: Optional[str] = None, **kwargs
|
||||||
):
|
):
|
||||||
validate_prompts(prompt, negative_prompt, MOONVALLEY_MAREY_MAX_PROMPT_LENGTH)
|
validate_prompts(prompt, negative_prompt, MOONVALLEY_MAREY_MAX_PROMPT_LENGTH)
|
||||||
@ -717,15 +717,15 @@ class MoonvalleyTxt2VideoNode(BaseMoonvalleyVideoNode):
|
|||||||
request=request,
|
request=request,
|
||||||
auth_kwargs=kwargs,
|
auth_kwargs=kwargs,
|
||||||
)
|
)
|
||||||
task_creation_response = initial_operation.execute()
|
task_creation_response = await initial_operation.execute()
|
||||||
validate_task_creation_response(task_creation_response)
|
validate_task_creation_response(task_creation_response)
|
||||||
task_id = task_creation_response.id
|
task_id = task_creation_response.id
|
||||||
|
|
||||||
final_response = self.get_response(
|
final_response = await self.get_response(
|
||||||
task_id, auth_kwargs=kwargs, node_id=unique_id
|
task_id, auth_kwargs=kwargs, node_id=unique_id
|
||||||
)
|
)
|
||||||
|
|
||||||
video = download_url_to_video_output(final_response.output_url)
|
video = await download_url_to_video_output(final_response.output_url)
|
||||||
return (video,)
|
return (video,)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -122,7 +122,7 @@ class PikaNodeBase(ComfyNodeABC):
|
|||||||
FUNCTION = "api_call"
|
FUNCTION = "api_call"
|
||||||
RETURN_TYPES = ("VIDEO",)
|
RETURN_TYPES = ("VIDEO",)
|
||||||
|
|
||||||
def poll_for_task_status(
|
async def poll_for_task_status(
|
||||||
self,
|
self,
|
||||||
task_id: str,
|
task_id: str,
|
||||||
auth_kwargs: Optional[dict[str, str]] = None,
|
auth_kwargs: Optional[dict[str, str]] = None,
|
||||||
@ -152,9 +152,9 @@ class PikaNodeBase(ComfyNodeABC):
|
|||||||
node_id=node_id,
|
node_id=node_id,
|
||||||
estimated_duration=60
|
estimated_duration=60
|
||||||
)
|
)
|
||||||
return polling_operation.execute()
|
return await polling_operation.execute()
|
||||||
|
|
||||||
def execute_task(
|
async def execute_task(
|
||||||
self,
|
self,
|
||||||
initial_operation: SynchronousOperation[R, PikaGenerateResponse],
|
initial_operation: SynchronousOperation[R, PikaGenerateResponse],
|
||||||
auth_kwargs: Optional[dict[str, str]] = None,
|
auth_kwargs: Optional[dict[str, str]] = None,
|
||||||
@ -169,14 +169,14 @@ class PikaNodeBase(ComfyNodeABC):
|
|||||||
Returns:
|
Returns:
|
||||||
A tuple containing the video file as a VIDEO output.
|
A tuple containing the video file as a VIDEO output.
|
||||||
"""
|
"""
|
||||||
initial_response = initial_operation.execute()
|
initial_response = await initial_operation.execute()
|
||||||
if not is_valid_initial_response(initial_response):
|
if not is_valid_initial_response(initial_response):
|
||||||
error_msg = f"Pika initial request failed. Code: {initial_response.code}, Message: {initial_response.message}, Data: {initial_response.data}"
|
error_msg = f"Pika initial request failed. Code: {initial_response.code}, Message: {initial_response.message}, Data: {initial_response.data}"
|
||||||
logging.error(error_msg)
|
logging.error(error_msg)
|
||||||
raise PikaApiError(error_msg)
|
raise PikaApiError(error_msg)
|
||||||
|
|
||||||
task_id = initial_response.video_id
|
task_id = initial_response.video_id
|
||||||
final_response = self.poll_for_task_status(task_id, auth_kwargs)
|
final_response = await self.poll_for_task_status(task_id, auth_kwargs)
|
||||||
if not is_valid_video_response(final_response):
|
if not is_valid_video_response(final_response):
|
||||||
error_msg = (
|
error_msg = (
|
||||||
f"Pika task {task_id} succeeded but no video data found in response."
|
f"Pika task {task_id} succeeded but no video data found in response."
|
||||||
@ -187,7 +187,7 @@ class PikaNodeBase(ComfyNodeABC):
|
|||||||
video_url = str(final_response.url)
|
video_url = str(final_response.url)
|
||||||
logging.info("Pika task %s succeeded. Video URL: %s", task_id, video_url)
|
logging.info("Pika task %s succeeded. Video URL: %s", task_id, video_url)
|
||||||
|
|
||||||
return (download_url_to_video_output(video_url),)
|
return (await download_url_to_video_output(video_url),)
|
||||||
|
|
||||||
|
|
||||||
class PikaImageToVideoV2_2(PikaNodeBase):
|
class PikaImageToVideoV2_2(PikaNodeBase):
|
||||||
@ -212,7 +212,7 @@ class PikaImageToVideoV2_2(PikaNodeBase):
|
|||||||
|
|
||||||
DESCRIPTION = "Sends an image and prompt to the Pika API v2.2 to generate a video."
|
DESCRIPTION = "Sends an image and prompt to the Pika API v2.2 to generate a video."
|
||||||
|
|
||||||
def api_call(
|
async def api_call(
|
||||||
self,
|
self,
|
||||||
image: torch.Tensor,
|
image: torch.Tensor,
|
||||||
prompt_text: str,
|
prompt_text: str,
|
||||||
@ -251,7 +251,7 @@ class PikaImageToVideoV2_2(PikaNodeBase):
|
|||||||
auth_kwargs=kwargs,
|
auth_kwargs=kwargs,
|
||||||
)
|
)
|
||||||
|
|
||||||
return self.execute_task(initial_operation, auth_kwargs=kwargs, node_id=unique_id)
|
return await self.execute_task(initial_operation, auth_kwargs=kwargs, node_id=unique_id)
|
||||||
|
|
||||||
|
|
||||||
class PikaTextToVideoNodeV2_2(PikaNodeBase):
|
class PikaTextToVideoNodeV2_2(PikaNodeBase):
|
||||||
@ -281,7 +281,7 @@ class PikaTextToVideoNodeV2_2(PikaNodeBase):
|
|||||||
|
|
||||||
DESCRIPTION = "Sends a text prompt to the Pika API v2.2 to generate a video."
|
DESCRIPTION = "Sends a text prompt to the Pika API v2.2 to generate a video."
|
||||||
|
|
||||||
def api_call(
|
async def api_call(
|
||||||
self,
|
self,
|
||||||
prompt_text: str,
|
prompt_text: str,
|
||||||
negative_prompt: str,
|
negative_prompt: str,
|
||||||
@ -311,7 +311,7 @@ class PikaTextToVideoNodeV2_2(PikaNodeBase):
|
|||||||
content_type="application/x-www-form-urlencoded",
|
content_type="application/x-www-form-urlencoded",
|
||||||
)
|
)
|
||||||
|
|
||||||
return self.execute_task(initial_operation, auth_kwargs=kwargs, node_id=unique_id)
|
return await self.execute_task(initial_operation, auth_kwargs=kwargs, node_id=unique_id)
|
||||||
|
|
||||||
|
|
||||||
class PikaScenesV2_2(PikaNodeBase):
|
class PikaScenesV2_2(PikaNodeBase):
|
||||||
@ -361,7 +361,7 @@ class PikaScenesV2_2(PikaNodeBase):
|
|||||||
|
|
||||||
DESCRIPTION = "Combine your images to create a video with the objects in them. Upload multiple images as ingredients and generate a high-quality video that incorporates all of them."
|
DESCRIPTION = "Combine your images to create a video with the objects in them. Upload multiple images as ingredients and generate a high-quality video that incorporates all of them."
|
||||||
|
|
||||||
def api_call(
|
async def api_call(
|
||||||
self,
|
self,
|
||||||
prompt_text: str,
|
prompt_text: str,
|
||||||
negative_prompt: str,
|
negative_prompt: str,
|
||||||
@ -420,7 +420,7 @@ class PikaScenesV2_2(PikaNodeBase):
|
|||||||
auth_kwargs=kwargs,
|
auth_kwargs=kwargs,
|
||||||
)
|
)
|
||||||
|
|
||||||
return self.execute_task(initial_operation, auth_kwargs=kwargs, node_id=unique_id)
|
return await self.execute_task(initial_operation, auth_kwargs=kwargs, node_id=unique_id)
|
||||||
|
|
||||||
|
|
||||||
class PikAdditionsNode(PikaNodeBase):
|
class PikAdditionsNode(PikaNodeBase):
|
||||||
@ -462,7 +462,7 @@ class PikAdditionsNode(PikaNodeBase):
|
|||||||
|
|
||||||
DESCRIPTION = "Add any object or image into your video. Upload a video and specify what you'd like to add to create a seamlessly integrated result."
|
DESCRIPTION = "Add any object or image into your video. Upload a video and specify what you'd like to add to create a seamlessly integrated result."
|
||||||
|
|
||||||
def api_call(
|
async def api_call(
|
||||||
self,
|
self,
|
||||||
video: VideoInput,
|
video: VideoInput,
|
||||||
image: torch.Tensor,
|
image: torch.Tensor,
|
||||||
@ -481,10 +481,10 @@ class PikAdditionsNode(PikaNodeBase):
|
|||||||
image_bytes_io = tensor_to_bytesio(image)
|
image_bytes_io = tensor_to_bytesio(image)
|
||||||
image_bytes_io.seek(0)
|
image_bytes_io.seek(0)
|
||||||
|
|
||||||
pika_files = [
|
pika_files = {
|
||||||
("video", ("video.mp4", video_bytes_io, "video/mp4")),
|
"video": ("video.mp4", video_bytes_io, "video/mp4"),
|
||||||
("image", ("image.png", image_bytes_io, "image/png")),
|
"image": ("image.png", image_bytes_io, "image/png"),
|
||||||
]
|
}
|
||||||
|
|
||||||
# Prepare non-file data
|
# Prepare non-file data
|
||||||
pika_request_data = PikaBodyGeneratePikadditionsGeneratePikadditionsPost(
|
pika_request_data = PikaBodyGeneratePikadditionsGeneratePikadditionsPost(
|
||||||
@ -506,7 +506,7 @@ class PikAdditionsNode(PikaNodeBase):
|
|||||||
auth_kwargs=kwargs,
|
auth_kwargs=kwargs,
|
||||||
)
|
)
|
||||||
|
|
||||||
return self.execute_task(initial_operation, auth_kwargs=kwargs, node_id=unique_id)
|
return await self.execute_task(initial_operation, auth_kwargs=kwargs, node_id=unique_id)
|
||||||
|
|
||||||
|
|
||||||
class PikaSwapsNode(PikaNodeBase):
|
class PikaSwapsNode(PikaNodeBase):
|
||||||
@ -558,7 +558,7 @@ class PikaSwapsNode(PikaNodeBase):
|
|||||||
DESCRIPTION = "Swap out any object or region of your video with a new image or object. Define areas to replace either with a mask or coordinates."
|
DESCRIPTION = "Swap out any object or region of your video with a new image or object. Define areas to replace either with a mask or coordinates."
|
||||||
RETURN_TYPES = ("VIDEO",)
|
RETURN_TYPES = ("VIDEO",)
|
||||||
|
|
||||||
def api_call(
|
async def api_call(
|
||||||
self,
|
self,
|
||||||
video: VideoInput,
|
video: VideoInput,
|
||||||
image: torch.Tensor,
|
image: torch.Tensor,
|
||||||
@ -587,11 +587,11 @@ class PikaSwapsNode(PikaNodeBase):
|
|||||||
image_bytes_io = tensor_to_bytesio(image)
|
image_bytes_io = tensor_to_bytesio(image)
|
||||||
image_bytes_io.seek(0)
|
image_bytes_io.seek(0)
|
||||||
|
|
||||||
pika_files = [
|
pika_files = {
|
||||||
("video", ("video.mp4", video_bytes_io, "video/mp4")),
|
"video": ("video.mp4", video_bytes_io, "video/mp4"),
|
||||||
("image", ("image.png", image_bytes_io, "image/png")),
|
"image": ("image.png", image_bytes_io, "image/png"),
|
||||||
("modifyRegionMask", ("mask.png", mask_bytes_io, "image/png")),
|
"modifyRegionMask": ("mask.png", mask_bytes_io, "image/png"),
|
||||||
]
|
}
|
||||||
|
|
||||||
# Prepare non-file data
|
# Prepare non-file data
|
||||||
pika_request_data = PikaBodyGeneratePikaswapsGeneratePikaswapsPost(
|
pika_request_data = PikaBodyGeneratePikaswapsGeneratePikaswapsPost(
|
||||||
@ -613,7 +613,7 @@ class PikaSwapsNode(PikaNodeBase):
|
|||||||
auth_kwargs=kwargs,
|
auth_kwargs=kwargs,
|
||||||
)
|
)
|
||||||
|
|
||||||
return self.execute_task(initial_operation, auth_kwargs=kwargs, node_id=unique_id)
|
return await self.execute_task(initial_operation, auth_kwargs=kwargs, node_id=unique_id)
|
||||||
|
|
||||||
|
|
||||||
class PikaffectsNode(PikaNodeBase):
|
class PikaffectsNode(PikaNodeBase):
|
||||||
@ -664,7 +664,7 @@ class PikaffectsNode(PikaNodeBase):
|
|||||||
|
|
||||||
DESCRIPTION = "Generate a video with a specific Pikaffect. Supported Pikaffects: Cake-ify, Crumble, Crush, Decapitate, Deflate, Dissolve, Explode, Eye-pop, Inflate, Levitate, Melt, Peel, Poke, Squish, Ta-da, Tear"
|
DESCRIPTION = "Generate a video with a specific Pikaffect. Supported Pikaffects: Cake-ify, Crumble, Crush, Decapitate, Deflate, Dissolve, Explode, Eye-pop, Inflate, Levitate, Melt, Peel, Poke, Squish, Ta-da, Tear"
|
||||||
|
|
||||||
def api_call(
|
async def api_call(
|
||||||
self,
|
self,
|
||||||
image: torch.Tensor,
|
image: torch.Tensor,
|
||||||
pikaffect: str,
|
pikaffect: str,
|
||||||
@ -693,7 +693,7 @@ class PikaffectsNode(PikaNodeBase):
|
|||||||
auth_kwargs=kwargs,
|
auth_kwargs=kwargs,
|
||||||
)
|
)
|
||||||
|
|
||||||
return self.execute_task(initial_operation, auth_kwargs=kwargs, node_id=unique_id)
|
return await self.execute_task(initial_operation, auth_kwargs=kwargs, node_id=unique_id)
|
||||||
|
|
||||||
|
|
||||||
class PikaStartEndFrameNode2_2(PikaNodeBase):
|
class PikaStartEndFrameNode2_2(PikaNodeBase):
|
||||||
@ -718,7 +718,7 @@ class PikaStartEndFrameNode2_2(PikaNodeBase):
|
|||||||
|
|
||||||
DESCRIPTION = "Generate a video by combining your first and last frame. Upload two images to define the start and end points, and let the AI create a smooth transition between them."
|
DESCRIPTION = "Generate a video by combining your first and last frame. Upload two images to define the start and end points, and let the AI create a smooth transition between them."
|
||||||
|
|
||||||
def api_call(
|
async def api_call(
|
||||||
self,
|
self,
|
||||||
image_start: torch.Tensor,
|
image_start: torch.Tensor,
|
||||||
image_end: torch.Tensor,
|
image_end: torch.Tensor,
|
||||||
@ -732,10 +732,7 @@ class PikaStartEndFrameNode2_2(PikaNodeBase):
|
|||||||
) -> tuple[VideoFromFile]:
|
) -> tuple[VideoFromFile]:
|
||||||
|
|
||||||
pika_files = [
|
pika_files = [
|
||||||
(
|
("keyFrames", ("image_start.png", tensor_to_bytesio(image_start), "image/png")),
|
||||||
"keyFrames",
|
|
||||||
("image_start.png", tensor_to_bytesio(image_start), "image/png"),
|
|
||||||
),
|
|
||||||
("keyFrames", ("image_end.png", tensor_to_bytesio(image_end), "image/png")),
|
("keyFrames", ("image_end.png", tensor_to_bytesio(image_end), "image/png")),
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -758,7 +755,7 @@ class PikaStartEndFrameNode2_2(PikaNodeBase):
|
|||||||
auth_kwargs=kwargs,
|
auth_kwargs=kwargs,
|
||||||
)
|
)
|
||||||
|
|
||||||
return self.execute_task(initial_operation, auth_kwargs=kwargs, node_id=unique_id)
|
return await self.execute_task(initial_operation, auth_kwargs=kwargs, node_id=unique_id)
|
||||||
|
|
||||||
|
|
||||||
NODE_CLASS_MAPPINGS = {
|
NODE_CLASS_MAPPINGS = {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user