npcpy 1.3.18__py3-none-any.whl → 1.3.19__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- npcpy/serve.py +84 -1
- {npcpy-1.3.18.dist-info → npcpy-1.3.19.dist-info}/METADATA +1 -1
- {npcpy-1.3.18.dist-info → npcpy-1.3.19.dist-info}/RECORD +6 -6
- {npcpy-1.3.18.dist-info → npcpy-1.3.19.dist-info}/WHEEL +0 -0
- {npcpy-1.3.18.dist-info → npcpy-1.3.19.dist-info}/licenses/LICENSE +0 -0
- {npcpy-1.3.18.dist-info → npcpy-1.3.19.dist-info}/top_level.txt +0 -0
npcpy/serve.py
CHANGED
|
@@ -58,7 +58,7 @@ import base64
|
|
|
58
58
|
import shutil
|
|
59
59
|
import uuid
|
|
60
60
|
|
|
61
|
-
from npcpy.llm_funcs import gen_image, breathe
|
|
61
|
+
from npcpy.llm_funcs import gen_image, gen_video, breathe
|
|
62
62
|
|
|
63
63
|
from sqlalchemy import create_engine, text
|
|
64
64
|
from sqlalchemy.orm import sessionmaker
|
|
@@ -4333,6 +4333,89 @@ def get_image_models_api():
|
|
|
4333
4333
|
return jsonify({"models": [], "error": str(e)}), 500
|
|
4334
4334
|
|
|
4335
4335
|
|
|
4336
|
+
@app.route("/api/generate_video", methods=["POST"])
|
|
4337
|
+
def generate_video_api():
|
|
4338
|
+
"""
|
|
4339
|
+
API endpoint for video generation.
|
|
4340
|
+
"""
|
|
4341
|
+
try:
|
|
4342
|
+
data = request.get_json()
|
|
4343
|
+
prompt = data.get("prompt", "")
|
|
4344
|
+
model = data.get("model", "veo-3.1-generate-preview")
|
|
4345
|
+
provider = data.get("provider", "gemini")
|
|
4346
|
+
duration = data.get("duration", 5)
|
|
4347
|
+
output_dir = data.get("output_dir") # Optional user-specified path
|
|
4348
|
+
negative_prompt = data.get("negative_prompt", "")
|
|
4349
|
+
reference_image = data.get("reference_image") # Optional base64 image
|
|
4350
|
+
|
|
4351
|
+
if not prompt:
|
|
4352
|
+
return jsonify({"error": "Prompt is required"}), 400
|
|
4353
|
+
|
|
4354
|
+
# Create output directory - use user-specified path or default to ~/.npcsh/videos
|
|
4355
|
+
if output_dir:
|
|
4356
|
+
save_dir = os.path.expanduser(output_dir)
|
|
4357
|
+
else:
|
|
4358
|
+
save_dir = os.path.expanduser("~/.npcsh/videos")
|
|
4359
|
+
os.makedirs(save_dir, exist_ok=True)
|
|
4360
|
+
|
|
4361
|
+
# Generate unique filename
|
|
4362
|
+
timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
|
|
4363
|
+
output_filename = f"video_{timestamp}.mp4"
|
|
4364
|
+
output_path = os.path.join(save_dir, output_filename)
|
|
4365
|
+
|
|
4366
|
+
# Calculate num_frames based on duration (assuming ~25fps for diffusers)
|
|
4367
|
+
num_frames = int(duration * 25) if provider == "diffusers" else 25
|
|
4368
|
+
|
|
4369
|
+
print(f"Generating video with model={model}, provider={provider}, duration={duration}s")
|
|
4370
|
+
|
|
4371
|
+
result = gen_video(
|
|
4372
|
+
prompt=prompt,
|
|
4373
|
+
model=model,
|
|
4374
|
+
provider=provider,
|
|
4375
|
+
output_path=output_path,
|
|
4376
|
+
num_frames=num_frames,
|
|
4377
|
+
negative_prompt=negative_prompt,
|
|
4378
|
+
)
|
|
4379
|
+
|
|
4380
|
+
if result and "output" in result:
|
|
4381
|
+
# Read the generated video file and encode to base64
|
|
4382
|
+
video_path = output_path
|
|
4383
|
+
if os.path.exists(video_path):
|
|
4384
|
+
with open(video_path, "rb") as f:
|
|
4385
|
+
video_data = f.read()
|
|
4386
|
+
video_base64 = base64.b64encode(video_data).decode("utf-8")
|
|
4387
|
+
|
|
4388
|
+
return jsonify({
|
|
4389
|
+
"success": True,
|
|
4390
|
+
"video_path": video_path,
|
|
4391
|
+
"video_base64": f"data:video/mp4;base64,{video_base64}",
|
|
4392
|
+
"message": result.get("output", "Video generated successfully")
|
|
4393
|
+
})
|
|
4394
|
+
else:
|
|
4395
|
+
return jsonify({"error": "Video file was not created"}), 500
|
|
4396
|
+
else:
|
|
4397
|
+
return jsonify({"error": result.get("output", "Video generation failed")}), 500
|
|
4398
|
+
|
|
4399
|
+
except Exception as e:
|
|
4400
|
+
print(f"Error generating video: {e}")
|
|
4401
|
+
traceback.print_exc()
|
|
4402
|
+
return jsonify({"error": str(e)}), 500
|
|
4403
|
+
|
|
4404
|
+
|
|
4405
|
+
@app.route("/api/video_models", methods=["GET"])
|
|
4406
|
+
def get_video_models_api():
|
|
4407
|
+
"""
|
|
4408
|
+
API endpoint to retrieve available video generation models.
|
|
4409
|
+
"""
|
|
4410
|
+
video_models = [
|
|
4411
|
+
# Google Veo via Gemini API (requires GEMINI_API_KEY)
|
|
4412
|
+
{"value": "veo-3.1-generate-preview", "display_name": "Veo 3.1 | gemini", "provider": "gemini", "max_duration": 8},
|
|
4413
|
+
{"value": "veo-3.1-fast-generate-preview", "display_name": "Veo 3.1 Fast | gemini", "provider": "gemini", "max_duration": 8},
|
|
4414
|
+
{"value": "veo-2.0-generate-001", "display_name": "Veo 2 | gemini", "provider": "gemini", "max_duration": 8},
|
|
4415
|
+
# Diffusers - damo-vilab/text-to-video-ms-1.7b (local)
|
|
4416
|
+
{"value": "damo-vilab/text-to-video-ms-1.7b", "display_name": "ModelScope 1.7B (Local) | diffusers", "provider": "diffusers", "max_duration": 4},
|
|
4417
|
+
]
|
|
4418
|
+
return jsonify({"models": video_models, "error": None})
|
|
4336
4419
|
|
|
4337
4420
|
|
|
4338
4421
|
|
|
@@ -7,7 +7,7 @@ npcpy/npc_array.py,sha256=5qjaA9KjmJ_Zk_VxLrCyVrj73aDXpm3iJf0ngq1yIJk,45721
|
|
|
7
7
|
npcpy/npc_compiler.py,sha256=6-SYOddpi2jTJ1KtbMxtNGC7ksaiuuLd59bmc0eiOUA,121619
|
|
8
8
|
npcpy/npc_sysenv.py,sha256=1E2zwMj7aPrtRJuJSowGkvNApi07Vue3FhXsipi1XDs,45251
|
|
9
9
|
npcpy/npcs.py,sha256=eExuVsbTfrRobTRRptRpDm46jCLWUgbvy4_U7IUQo-c,744
|
|
10
|
-
npcpy/serve.py,sha256=
|
|
10
|
+
npcpy/serve.py,sha256=G8slQRslfOnGnSUD8GP1IOiqQhUWu6vF_azClvI7jLs,279284
|
|
11
11
|
npcpy/tools.py,sha256=A5_oVmZkzGnI3BI-NmneuxeXQq-r29PbpAZP4nV4jrc,5303
|
|
12
12
|
npcpy/data/__init__.py,sha256=1tcoChR-Hjn905JDLqaW9ElRmcISCTJdE7BGXPlym2Q,642
|
|
13
13
|
npcpy/data/audio.py,sha256=o4auV8DQrAmZ4y84U3SofiwEuq5-ZBjGEZipQ9zPpGQ,22816
|
|
@@ -53,8 +53,8 @@ npcpy/work/browser.py,sha256=p2PeaoZdAXipFuAgKCCB3aXXLE_p3yIRqC87KlZKZWc,679
|
|
|
53
53
|
npcpy/work/desktop.py,sha256=F3I8mUtJp6LAkXodsh8hGZIncoads6c_2Utty-0EdDA,2986
|
|
54
54
|
npcpy/work/plan.py,sha256=QyUwg8vElWiHuoS-xK4jXTxxHvkMD3VkaCEsCmrEPQk,8300
|
|
55
55
|
npcpy/work/trigger.py,sha256=P1Y8u1wQRsS2WACims_2IdkBEar-iBQix-2TDWoW0OM,9948
|
|
56
|
-
npcpy-1.3.
|
|
57
|
-
npcpy-1.3.
|
|
58
|
-
npcpy-1.3.
|
|
59
|
-
npcpy-1.3.
|
|
60
|
-
npcpy-1.3.
|
|
56
|
+
npcpy-1.3.19.dist-info/licenses/LICENSE,sha256=j0YPvce7Ng9e32zYOu0EmXjXeJ0Nwawd0RA3uSGGH4E,1070
|
|
57
|
+
npcpy-1.3.19.dist-info/METADATA,sha256=18bGYxznkKrwP59mZ_06rQfMFQBe_hdAjB_VbHyZBYY,37870
|
|
58
|
+
npcpy-1.3.19.dist-info/WHEEL,sha256=qELbo2s1Yzl39ZmrAibXA2jjPLUYfnVhUNTlyF1rq0Y,92
|
|
59
|
+
npcpy-1.3.19.dist-info/top_level.txt,sha256=g1pbSvrOOncB74Bg5-J0Olg4V0A5VzDw-Xz5YObq8BU,6
|
|
60
|
+
npcpy-1.3.19.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|