Skip to content

Commit 4e2110c

Browse files
authored
feat(Pika-API-nodes): use new API client (#10608)
1 parent e617cdd commit 4e2110c

File tree

2 files changed

+57
-124
lines changed

2 files changed

+57
-124
lines changed

comfy_api_nodes/nodes_pika.py

Lines changed: 57 additions & 124 deletions
Original file line numberDiff line numberDiff line change
@@ -7,24 +7,23 @@
77

88
from io import BytesIO
99
import logging
10-
from typing import Optional, TypeVar
10+
from typing import Optional
1111

1212
import torch
1313

1414
from typing_extensions import override
1515
from comfy_api.latest import ComfyExtension, IO
1616
from comfy_api.input_impl.video_types import VideoCodec, VideoContainer, VideoInput
17-
from comfy_api_nodes.apis import pika_defs
18-
from comfy_api_nodes.apis.client import (
17+
from comfy_api_nodes.apis import pika_api as pika_defs
18+
from comfy_api_nodes.util import (
19+
validate_string,
20+
download_url_to_video_output,
21+
tensor_to_bytesio,
1922
ApiEndpoint,
20-
EmptyRequest,
21-
HttpMethod,
22-
PollingOperation,
23-
SynchronousOperation,
23+
sync_op,
24+
poll_op,
2425
)
25-
from comfy_api_nodes.util import validate_string, download_url_to_video_output, tensor_to_bytesio
2626

27-
R = TypeVar("R")
2827

2928
PATH_PIKADDITIONS = "/proxy/pika/generate/pikadditions"
3029
PATH_PIKASWAPS = "/proxy/pika/generate/pikaswaps"
@@ -40,28 +39,18 @@
4039

4140

4241
async def execute_task(
43-
initial_operation: SynchronousOperation[R, pika_defs.PikaGenerateResponse],
44-
auth_kwargs: Optional[dict[str, str]] = None,
45-
node_id: Optional[str] = None,
42+
task_id: str,
43+
cls: type[IO.ComfyNode],
4644
) -> IO.NodeOutput:
47-
task_id = (await initial_operation.execute()).video_id
48-
final_response: pika_defs.PikaVideoResponse = await PollingOperation(
49-
poll_endpoint=ApiEndpoint(
50-
path=f"{PATH_VIDEO_GET}/{task_id}",
51-
method=HttpMethod.GET,
52-
request_model=EmptyRequest,
53-
response_model=pika_defs.PikaVideoResponse,
54-
),
55-
completed_statuses=["finished"],
56-
failed_statuses=["failed", "cancelled"],
45+
final_response: pika_defs.PikaVideoResponse = await poll_op(
46+
cls,
47+
ApiEndpoint(path=f"{PATH_VIDEO_GET}/{task_id}"),
48+
response_model=pika_defs.PikaVideoResponse,
5749
status_extractor=lambda response: (response.status.value if response.status else None),
5850
progress_extractor=lambda response: (response.progress if hasattr(response, "progress") else None),
59-
auth_kwargs=auth_kwargs,
60-
result_url_extractor=lambda response: (response.url if hasattr(response, "url") else None),
61-
node_id=node_id,
6251
estimated_duration=60,
6352
max_poll_attempts=240,
64-
).execute()
53+
)
6554
if not final_response.url:
6655
error_msg = f"Pika task {task_id} succeeded but no video data found in response:\n{final_response}"
6756
logging.error(error_msg)
@@ -124,23 +113,15 @@ async def execute(
124113
resolution=resolution,
125114
duration=duration,
126115
)
127-
auth = {
128-
"auth_token": cls.hidden.auth_token_comfy_org,
129-
"comfy_api_key": cls.hidden.api_key_comfy_org,
130-
}
131-
initial_operation = SynchronousOperation(
132-
endpoint=ApiEndpoint(
133-
path=PATH_IMAGE_TO_VIDEO,
134-
method=HttpMethod.POST,
135-
request_model=pika_defs.PikaBodyGenerate22I2vGenerate22I2vPost,
136-
response_model=pika_defs.PikaGenerateResponse,
137-
),
138-
request=pika_request_data,
116+
initial_operation = await sync_op(
117+
cls,
118+
ApiEndpoint(path=PATH_IMAGE_TO_VIDEO, method="POST"),
119+
response_model=pika_defs.PikaGenerateResponse,
120+
data=pika_request_data,
139121
files=pika_files,
140122
content_type="multipart/form-data",
141-
auth_kwargs=auth,
142123
)
143-
return await execute_task(initial_operation, auth_kwargs=auth, node_id=cls.hidden.unique_id)
124+
return await execute_task(initial_operation.video_id, cls)
144125

145126

146127
class PikaTextToVideoNode(IO.ComfyNode):
@@ -183,29 +164,21 @@ async def execute(
183164
duration: int,
184165
aspect_ratio: float,
185166
) -> IO.NodeOutput:
186-
auth = {
187-
"auth_token": cls.hidden.auth_token_comfy_org,
188-
"comfy_api_key": cls.hidden.api_key_comfy_org,
189-
}
190-
initial_operation = SynchronousOperation(
191-
endpoint=ApiEndpoint(
192-
path=PATH_TEXT_TO_VIDEO,
193-
method=HttpMethod.POST,
194-
request_model=pika_defs.PikaBodyGenerate22T2vGenerate22T2vPost,
195-
response_model=pika_defs.PikaGenerateResponse,
196-
),
197-
request=pika_defs.PikaBodyGenerate22T2vGenerate22T2vPost(
167+
initial_operation = await sync_op(
168+
cls,
169+
ApiEndpoint(path=PATH_TEXT_TO_VIDEO, method="POST"),
170+
response_model=pika_defs.PikaGenerateResponse,
171+
data=pika_defs.PikaBodyGenerate22T2vGenerate22T2vPost(
198172
promptText=prompt_text,
199173
negativePrompt=negative_prompt,
200174
seed=seed,
201175
resolution=resolution,
202176
duration=duration,
203177
aspectRatio=aspect_ratio,
204178
),
205-
auth_kwargs=auth,
206179
content_type="application/x-www-form-urlencoded",
207180
)
208-
return await execute_task(initial_operation, auth_kwargs=auth, node_id=cls.hidden.unique_id)
181+
return await execute_task(initial_operation.video_id, cls)
209182

210183

211184
class PikaScenes(IO.ComfyNode):
@@ -309,24 +282,16 @@ async def execute(
309282
duration=duration,
310283
aspectRatio=aspect_ratio,
311284
)
312-
auth = {
313-
"auth_token": cls.hidden.auth_token_comfy_org,
314-
"comfy_api_key": cls.hidden.api_key_comfy_org,
315-
}
316-
initial_operation = SynchronousOperation(
317-
endpoint=ApiEndpoint(
318-
path=PATH_PIKASCENES,
319-
method=HttpMethod.POST,
320-
request_model=pika_defs.PikaBodyGenerate22C2vGenerate22PikascenesPost,
321-
response_model=pika_defs.PikaGenerateResponse,
322-
),
323-
request=pika_request_data,
285+
initial_operation = await sync_op(
286+
cls,
287+
ApiEndpoint(path=PATH_PIKASCENES, method="POST"),
288+
response_model=pika_defs.PikaGenerateResponse,
289+
data=pika_request_data,
324290
files=pika_files,
325291
content_type="multipart/form-data",
326-
auth_kwargs=auth,
327292
)
328293

329-
return await execute_task(initial_operation, auth_kwargs=auth, node_id=cls.hidden.unique_id)
294+
return await execute_task(initial_operation.video_id, cls)
330295

331296

332297
class PikAdditionsNode(IO.ComfyNode):
@@ -383,24 +348,16 @@ async def execute(
383348
negativePrompt=negative_prompt,
384349
seed=seed,
385350
)
386-
auth = {
387-
"auth_token": cls.hidden.auth_token_comfy_org,
388-
"comfy_api_key": cls.hidden.api_key_comfy_org,
389-
}
390-
initial_operation = SynchronousOperation(
391-
endpoint=ApiEndpoint(
392-
path=PATH_PIKADDITIONS,
393-
method=HttpMethod.POST,
394-
request_model=pika_defs.PikaBodyGeneratePikadditionsGeneratePikadditionsPost,
395-
response_model=pika_defs.PikaGenerateResponse,
396-
),
397-
request=pika_request_data,
351+
initial_operation = await sync_op(
352+
cls,
353+
ApiEndpoint(path=PATH_PIKADDITIONS, method="POST"),
354+
response_model=pika_defs.PikaGenerateResponse,
355+
data=pika_request_data,
398356
files=pika_files,
399357
content_type="multipart/form-data",
400-
auth_kwargs=auth,
401358
)
402359

403-
return await execute_task(initial_operation, auth_kwargs=auth, node_id=cls.hidden.unique_id)
360+
return await execute_task(initial_operation.video_id, cls)
404361

405362

406363
class PikaSwapsNode(IO.ComfyNode):
@@ -472,23 +429,15 @@ async def execute(
472429
seed=seed,
473430
modifyRegionRoi=region_to_modify if region_to_modify else None,
474431
)
475-
auth = {
476-
"auth_token": cls.hidden.auth_token_comfy_org,
477-
"comfy_api_key": cls.hidden.api_key_comfy_org,
478-
}
479-
initial_operation = SynchronousOperation(
480-
endpoint=ApiEndpoint(
481-
path=PATH_PIKASWAPS,
482-
method=HttpMethod.POST,
483-
request_model=pika_defs.PikaBodyGeneratePikaswapsGeneratePikaswapsPost,
484-
response_model=pika_defs.PikaGenerateResponse,
485-
),
486-
request=pika_request_data,
432+
initial_operation = await sync_op(
433+
cls,
434+
ApiEndpoint(path=PATH_PIKASWAPS, method="POST"),
435+
response_model=pika_defs.PikaGenerateResponse,
436+
data=pika_request_data,
487437
files=pika_files,
488438
content_type="multipart/form-data",
489-
auth_kwargs=auth,
490439
)
491-
return await execute_task(initial_operation, auth_kwargs=auth, node_id=cls.hidden.unique_id)
440+
return await execute_task(initial_operation.video_id, cls)
492441

493442

494443
class PikaffectsNode(IO.ComfyNode):
@@ -528,28 +477,20 @@ async def execute(
528477
negative_prompt: str,
529478
seed: int,
530479
) -> IO.NodeOutput:
531-
auth = {
532-
"auth_token": cls.hidden.auth_token_comfy_org,
533-
"comfy_api_key": cls.hidden.api_key_comfy_org,
534-
}
535-
initial_operation = SynchronousOperation(
536-
endpoint=ApiEndpoint(
537-
path=PATH_PIKAFFECTS,
538-
method=HttpMethod.POST,
539-
request_model=pika_defs.PikaBodyGeneratePikaffectsGeneratePikaffectsPost,
540-
response_model=pika_defs.PikaGenerateResponse,
541-
),
542-
request=pika_defs.PikaBodyGeneratePikaffectsGeneratePikaffectsPost(
480+
initial_operation = await sync_op(
481+
cls,
482+
ApiEndpoint(path=PATH_PIKAFFECTS, method="POST"),
483+
response_model=pika_defs.PikaGenerateResponse,
484+
data=pika_defs.PikaBodyGeneratePikaffectsGeneratePikaffectsPost(
543485
pikaffect=pikaffect,
544486
promptText=prompt_text,
545487
negativePrompt=negative_prompt,
546488
seed=seed,
547489
),
548490
files={"image": ("image.png", tensor_to_bytesio(image), "image/png")},
549491
content_type="multipart/form-data",
550-
auth_kwargs=auth,
551492
)
552-
return await execute_task(initial_operation, auth_kwargs=auth, node_id=cls.hidden.unique_id)
493+
return await execute_task(initial_operation.video_id, cls)
553494

554495

555496
class PikaStartEndFrameNode(IO.ComfyNode):
@@ -592,18 +533,11 @@ async def execute(
592533
("keyFrames", ("image_start.png", tensor_to_bytesio(image_start), "image/png")),
593534
("keyFrames", ("image_end.png", tensor_to_bytesio(image_end), "image/png")),
594535
]
595-
auth = {
596-
"auth_token": cls.hidden.auth_token_comfy_org,
597-
"comfy_api_key": cls.hidden.api_key_comfy_org,
598-
}
599-
initial_operation = SynchronousOperation(
600-
endpoint=ApiEndpoint(
601-
path=PATH_PIKAFRAMES,
602-
method=HttpMethod.POST,
603-
request_model=pika_defs.PikaBodyGenerate22KeyframeGenerate22PikaframesPost,
604-
response_model=pika_defs.PikaGenerateResponse,
605-
),
606-
request=pika_defs.PikaBodyGenerate22KeyframeGenerate22PikaframesPost(
536+
initial_operation = await sync_op(
537+
cls,
538+
ApiEndpoint(path=PATH_PIKAFRAMES, method="POST"),
539+
response_model=pika_defs.PikaGenerateResponse,
540+
data=pika_defs.PikaBodyGenerate22KeyframeGenerate22PikaframesPost(
607541
promptText=prompt_text,
608542
negativePrompt=negative_prompt,
609543
seed=seed,
@@ -612,9 +546,8 @@ async def execute(
612546
),
613547
files=pika_files,
614548
content_type="multipart/form-data",
615-
auth_kwargs=auth,
616549
)
617-
return await execute_task(initial_operation, auth_kwargs=auth, node_id=cls.hidden.unique_id)
550+
return await execute_task(initial_operation.video_id, cls)
618551

619552

620553
class PikaApiNodesExtension(ComfyExtension):

0 commit comments

Comments
 (0)