Coverage for .venv/lib/python3.13/site-packages/litellm/proxy/video_endpoints/endpoints.py: 68%
207 statements
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-10 12:01 +0000
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-10 12:01 +0000
1#### Video Endpoints #####
3from typing import Final
5from fastapi import APIRouter, Depends, File, Form, Request, Response, UploadFile
6from fastapi.responses import ORJSONResponse
7from starlette.datastructures import UploadFile as StarletteUploadFile
9from litellm.proxy._types import *
10from litellm.proxy.auth.user_api_key_auth import UserAPIKeyAuth, user_api_key_auth
11from litellm.proxy.common_request_processing import ProxyBaseLLMRequestProcessing
12from litellm.proxy.common_utils.http_parsing_utils import _read_request_body
13from litellm.proxy.common_utils.openai_endpoint_utils import (
14 get_custom_llm_provider_from_request_body,
15 get_custom_llm_provider_from_request_headers,
16 get_custom_llm_provider_from_request_query,
17)
18from litellm.proxy.image_endpoints.endpoints import batch_to_bytesio
19from litellm.proxy.video_endpoints.utils import (
20 encode_character_id_in_response,
21 extract_model_from_target_model_names,
22 get_custom_provider_from_data,
23 video_reference_to_id,
24)
25from litellm.types.videos.utils import (
26 decode_character_id_with_provider,
27 decode_video_id_with_provider,
28)
30router: Final = APIRouter()
33@router.post(
34 "/v1/videos",
35 dependencies=[Depends(user_api_key_auth)],
36 response_class=ORJSONResponse,
37 tags=["videos"],
38)
39@router.post(
40 "/videos",
41 dependencies=[Depends(user_api_key_auth)],
42 response_class=ORJSONResponse,
43 tags=["videos"],
44)
45async def video_generation(
46 request: Request,
47 fastapi_response: Response,
48 input_reference: UploadFile | None = File(None),
49 user_api_key_dict: UserAPIKeyAuth = Depends(user_api_key_auth),
50):
51 """
52 Video generation endpoint for creating videos from text prompts.
54 Follows the OpenAI Videos API spec:
55 https://platform.openai.com/docs/api-reference/videos
57 Example:
58 ```bash
59 curl -X POST "http://localhost:4000/v1/videos" \
60 -H "Authorization: Bearer sk-1234" \
61 -H "Content-Type: application/json" \
62 -d '{
63 "model": "sora-2",
64 "prompt": "A beautiful sunset over the ocean"
65 }'
66 ```
67 """
68 from litellm.proxy.proxy_server import (
69 general_settings,
70 llm_router,
71 proxy_config,
72 proxy_logging_obj,
73 select_data_generator,
74 user_api_base,
75 user_max_tokens,
76 user_model,
77 user_request_timeout,
78 user_temperature,
79 version,
80 )
82 # Read request body
83 data: Final = await _read_request_body(request=request)
84 if input_reference is not None: 84 ↛ 85line 84 didn't jump to line 85 because the condition on line 84 was never true
85 input_reference_file: Final = await batch_to_bytesio([input_reference])
86 if input_reference_file:
87 data["input_reference"] = input_reference_file[0]
89 # Process request using ProxyBaseLLMRequestProcessing
90 processor: Final = ProxyBaseLLMRequestProcessing(data=data)
91 try:
92 generated: Final[object] = await processor.base_process_llm_request(
93 request=request,
94 fastapi_response=fastapi_response,
95 user_api_key_dict=user_api_key_dict,
96 route_type="avideo_generation",
97 proxy_logging_obj=proxy_logging_obj,
98 llm_router=llm_router,
99 general_settings=general_settings,
100 proxy_config=proxy_config,
101 select_data_generator=select_data_generator,
102 model=None,
103 user_model=user_model,
104 user_temperature=user_temperature,
105 user_request_timeout=user_request_timeout,
106 user_max_tokens=user_max_tokens,
107 user_api_base=user_api_base,
108 version=version,
109 )
110 except Exception as e:
111 raise await processor._handle_llm_api_exception(
112 e=e,
113 user_api_key_dict=user_api_key_dict,
114 proxy_logging_obj=proxy_logging_obj,
115 version=version,
116 )
117 else:
118 return generated
121@router.get(
122 "/v1/videos",
123 dependencies=[Depends(user_api_key_auth)],
124 response_class=ORJSONResponse,
125 tags=["videos"],
126)
127@router.get(
128 "/videos",
129 dependencies=[Depends(user_api_key_auth)],
130 response_class=ORJSONResponse,
131 tags=["videos"],
132)
133async def video_list(
134 request: Request,
135 fastapi_response: Response,
136 user_api_key_dict: UserAPIKeyAuth = Depends(user_api_key_auth),
137):
138 """
139 Video list endpoint for retrieving a list of videos.
141 Follows the OpenAI Videos API spec:
142 https://platform.openai.com/docs/api-reference/videos
144 Example:
145 ```bash
146 curl -X GET "http://localhost:4000/v1/videos" \
147 -H "Authorization: Bearer sk-1234"
148 ```
149 """
150 from litellm.proxy.proxy_server import (
151 general_settings,
152 llm_router,
153 proxy_config,
154 proxy_logging_obj,
155 select_data_generator,
156 user_api_base,
157 user_max_tokens,
158 user_model,
159 user_request_timeout,
160 user_temperature,
161 version,
162 )
164 # Read query parameters
165 query_params: Final = dict(request.query_params)
166 data: Final[dict[str, object]] = {"query_params": query_params}
168 # Extract custom_llm_provider from headers, query params, or body
169 custom_llm_provider: Final = (
170 get_custom_llm_provider_from_request_headers(request=request)
171 or get_custom_llm_provider_from_request_query(request=request)
172 or await get_custom_llm_provider_from_request_body(request=request)
173 )
174 if custom_llm_provider: 174 ↛ 175line 174 didn't jump to line 175 because the condition on line 174 was never true
175 data["custom_llm_provider"] = custom_llm_provider
176 # Process request using ProxyBaseLLMRequestProcessing
177 processor: Final = ProxyBaseLLMRequestProcessing(data=data)
178 try:
179 listed: Final[object] = await processor.base_process_llm_request(
180 request=request,
181 fastapi_response=fastapi_response,
182 user_api_key_dict=user_api_key_dict,
183 route_type="avideo_list",
184 proxy_logging_obj=proxy_logging_obj,
185 llm_router=llm_router,
186 general_settings=general_settings,
187 proxy_config=proxy_config,
188 select_data_generator=select_data_generator,
189 model=None,
190 user_model=user_model,
191 user_temperature=user_temperature,
192 user_request_timeout=user_request_timeout,
193 user_max_tokens=user_max_tokens,
194 user_api_base=user_api_base,
195 version=version,
196 )
197 except Exception as e:
198 raise await processor._handle_llm_api_exception(
199 e=e,
200 user_api_key_dict=user_api_key_dict,
201 proxy_logging_obj=proxy_logging_obj,
202 version=version,
203 )
204 else:
205 return listed
208@router.get(
209 "/v1/videos/{video_id}",
210 dependencies=[Depends(user_api_key_auth)],
211 response_class=ORJSONResponse,
212 tags=["videos"],
213)
214@router.get(
215 "/videos/{video_id}",
216 dependencies=[Depends(user_api_key_auth)],
217 response_class=ORJSONResponse,
218 tags=["videos"],
219)
220async def video_status(
221 video_id: str,
222 request: Request,
223 fastapi_response: Response,
224 user_api_key_dict: UserAPIKeyAuth = Depends(user_api_key_auth),
225):
226 """
227 Video status endpoint for retrieving video status and metadata.
229 Follows the OpenAI Videos API spec:
230 https://platform.openai.com/docs/api-reference/videos
232 Example:
233 ```bash
234 curl -X GET "http://localhost:4000/v1/videos/video_123" \
235 -H "Authorization: Bearer sk-1234"
236 ```
237 """
238 from litellm.proxy.proxy_server import (
239 general_settings,
240 llm_router,
241 proxy_config,
242 proxy_logging_obj,
243 select_data_generator,
244 user_api_base,
245 user_max_tokens,
246 user_model,
247 user_request_timeout,
248 user_temperature,
249 version,
250 )
252 # Create data with video_id
253 data: Final[dict[str, object]] = {"video_id": video_id}
255 decoded: Final = decode_video_id_with_provider(video_id)
256 provider_from_id: Final = decoded.get("custom_llm_provider")
257 model_id_from_decoded: Final = decoded.get("model_id")
259 custom_llm_provider: Final = (
260 get_custom_llm_provider_from_request_headers(request=request)
261 or get_custom_llm_provider_from_request_query(request=request)
262 or await get_custom_llm_provider_from_request_body(request=request)
263 or provider_from_id
264 or "openai"
265 )
266 if custom_llm_provider: 266 ↛ 271line 266 didn't jump to line 271 because the condition on line 266 was always true
267 data["custom_llm_provider"] = custom_llm_provider
269 # Resolve model_name from model_id if available
270 # This allows the router to automatically inject litellm_params from the model config
271 if model_id_from_decoded and llm_router: 271 ↛ 272line 271 didn't jump to line 272 because the condition on line 271 was never true
272 resolved_model: Final = llm_router.resolve_model_name_from_model_id(model_id_from_decoded)
273 if resolved_model:
274 data["model"] = resolved_model
276 # Process request using ProxyBaseLLMRequestProcessing
277 processor: Final = ProxyBaseLLMRequestProcessing(data=data)
278 try:
279 status: Final[object] = await processor.base_process_llm_request(
280 request=request,
281 fastapi_response=fastapi_response,
282 user_api_key_dict=user_api_key_dict,
283 route_type="avideo_status",
284 proxy_logging_obj=proxy_logging_obj,
285 llm_router=llm_router,
286 general_settings=general_settings,
287 proxy_config=proxy_config,
288 select_data_generator=select_data_generator,
289 model=None,
290 user_model=user_model,
291 user_temperature=user_temperature,
292 user_request_timeout=user_request_timeout,
293 user_max_tokens=user_max_tokens,
294 user_api_base=user_api_base,
295 version=version,
296 )
297 except Exception as e:
298 raise await processor._handle_llm_api_exception(
299 e=e,
300 user_api_key_dict=user_api_key_dict,
301 proxy_logging_obj=proxy_logging_obj,
302 version=version,
303 )
304 else:
305 return status
308@router.get(
309 "/v1/videos/{video_id}/content",
310 dependencies=[Depends(user_api_key_auth)],
311 response_class=Response,
312 tags=["videos"],
313)
314@router.get(
315 "/videos/{video_id}/content",
316 dependencies=[Depends(user_api_key_auth)],
317 response_class=Response,
318 tags=["videos"],
319)
320async def video_content(
321 video_id: str,
322 request: Request,
323 fastapi_response: Response,
324 user_api_key_dict: UserAPIKeyAuth = Depends(user_api_key_auth),
325):
326 """
327 Video content endpoint for downloading video content.
329 Follows the OpenAI Videos API spec:
330 https://platform.openai.com/docs/api-reference/videos
332 Example:
333 ```bash
334 curl -X GET "http://localhost:4000/v1/videos/{video_id}/content" \
335 -H "Authorization: Bearer sk-1234" \
336 --output video.mp4
337 ```
338 """
339 from litellm.proxy.proxy_server import (
340 general_settings,
341 llm_router,
342 proxy_config,
343 proxy_logging_obj,
344 select_data_generator,
345 user_api_base,
346 user_max_tokens,
347 user_model,
348 user_request_timeout,
349 user_temperature,
350 version,
351 )
353 # Create data with video_id
354 data: Final[dict[str, object]] = {"video_id": video_id}
356 decoded: Final = decode_video_id_with_provider(video_id)
357 provider_from_id: Final = decoded.get("custom_llm_provider")
358 model_id_from_decoded: Final = decoded.get("model_id")
360 custom_llm_provider: Final = (
361 get_custom_llm_provider_from_request_headers(request=request)
362 or get_custom_llm_provider_from_request_query(request=request)
363 or await get_custom_llm_provider_from_request_body(request=request)
364 or provider_from_id
365 )
366 if custom_llm_provider: 366 ↛ 367line 366 didn't jump to line 367 because the condition on line 366 was never true
367 data["custom_llm_provider"] = custom_llm_provider
369 # Resolve model_name from model_id if available
370 # This allows the router to automatically inject litellm_params from the model config
371 if model_id_from_decoded and llm_router: 371 ↛ 372line 371 didn't jump to line 372 because the condition on line 371 was never true
372 resolved_model: Final = llm_router.resolve_model_name_from_model_id(model_id_from_decoded)
373 if resolved_model:
374 data["model"] = resolved_model
375 # Process request using ProxyBaseLLMRequestProcessing
376 processor: Final = ProxyBaseLLMRequestProcessing(data=data)
377 try:
378 # Call the video content function directly to get raw bytes
379 video_bytes: Final = await processor.base_process_llm_request(
380 request=request,
381 fastapi_response=fastapi_response,
382 user_api_key_dict=user_api_key_dict,
383 route_type="avideo_content",
384 proxy_logging_obj=proxy_logging_obj,
385 llm_router=llm_router,
386 general_settings=general_settings,
387 proxy_config=proxy_config,
388 select_data_generator=select_data_generator,
389 model=None,
390 user_model=user_model,
391 user_temperature=user_temperature,
392 user_request_timeout=user_request_timeout,
393 user_max_tokens=user_max_tokens,
394 user_api_base=user_api_base,
395 version=version,
396 )
398 # Return raw video bytes with proper content type
399 return Response(
400 content=video_bytes,
401 media_type="video/mp4",
402 headers={"Content-Disposition": f"attachment; filename=video_{video_id}.mp4"},
403 )
404 except Exception as e:
405 raise await processor._handle_llm_api_exception(
406 e=e,
407 user_api_key_dict=user_api_key_dict,
408 proxy_logging_obj=proxy_logging_obj,
409 version=version,
410 )
413@router.post(
414 "/v1/videos/{video_id}/remix",
415 dependencies=[Depends(user_api_key_auth)],
416 response_class=ORJSONResponse,
417 tags=["videos"],
418)
419@router.post(
420 "/videos/{video_id}/remix",
421 dependencies=[Depends(user_api_key_auth)],
422 response_class=ORJSONResponse,
423 tags=["videos"],
424)
425async def video_remix(
426 video_id: str,
427 request: Request,
428 fastapi_response: Response,
429 user_api_key_dict: UserAPIKeyAuth = Depends(user_api_key_auth),
430):
431 """
432 Video remix endpoint for remixing existing videos with new prompts.
434 Follows the OpenAI Videos API spec:
435 https://platform.openai.com/docs/api-reference/videos
437 Example:
438 ```bash
439 curl -X POST "http://localhost:4000/v1/videos/video_123/remix" \
440 -H "Authorization: Bearer sk-1234" \
441 -H "Content-Type: application/json" \
442 -d '{
443 "prompt": "A new version with different colors"
444 }'
445 ```
446 """
447 from litellm.proxy.proxy_server import (
448 general_settings,
449 llm_router,
450 proxy_config,
451 proxy_logging_obj,
452 select_data_generator,
453 user_api_base,
454 user_max_tokens,
455 user_model,
456 user_request_timeout,
457 user_temperature,
458 version,
459 )
461 data: Final = await _read_request_body(request=request)
462 data["video_id"] = video_id
464 decoded: Final = decode_video_id_with_provider(video_id)
465 provider_from_id: Final = decoded.get("custom_llm_provider")
466 model_id_from_decoded: Final = decoded.get("model_id")
468 custom_llm_provider: Final = (
469 get_custom_llm_provider_from_request_headers(request=request)
470 or get_custom_llm_provider_from_request_query(request=request)
471 or data.get("custom_llm_provider")
472 or provider_from_id
473 )
474 if custom_llm_provider: 474 ↛ 475line 474 didn't jump to line 475 because the condition on line 474 was never true
475 data["custom_llm_provider"] = custom_llm_provider
477 # Resolve model_name from model_id if available
478 # This allows the router to automatically inject litellm_params from the model config
479 if model_id_from_decoded and llm_router: 479 ↛ 480line 479 didn't jump to line 480 because the condition on line 479 was never true
480 resolved_model: Final = llm_router.resolve_model_name_from_model_id(model_id_from_decoded)
481 if resolved_model:
482 data["model"] = resolved_model
484 # Process request using ProxyBaseLLMRequestProcessing
485 processor: Final = ProxyBaseLLMRequestProcessing(data=data)
486 try:
487 remixed: Final[object] = await processor.base_process_llm_request(
488 request=request,
489 fastapi_response=fastapi_response,
490 user_api_key_dict=user_api_key_dict,
491 route_type="avideo_remix",
492 proxy_logging_obj=proxy_logging_obj,
493 llm_router=llm_router,
494 general_settings=general_settings,
495 proxy_config=proxy_config,
496 select_data_generator=select_data_generator,
497 model=None,
498 user_model=user_model,
499 user_temperature=user_temperature,
500 user_request_timeout=user_request_timeout,
501 user_max_tokens=user_max_tokens,
502 user_api_base=user_api_base,
503 version=version,
504 )
505 except Exception as e:
506 raise await processor._handle_llm_api_exception(
507 e=e,
508 user_api_key_dict=user_api_key_dict,
509 proxy_logging_obj=proxy_logging_obj,
510 version=version,
511 )
512 else:
513 return remixed
516@router.post(
517 "/v1/videos/characters",
518 dependencies=[Depends(user_api_key_auth)],
519 response_class=ORJSONResponse,
520 tags=["videos"],
521)
522@router.post(
523 "/videos/characters",
524 dependencies=[Depends(user_api_key_auth)],
525 response_class=ORJSONResponse,
526 tags=["videos"],
527)
528async def video_create_character(
529 request: Request,
530 fastapi_response: Response,
531 video: UploadFile = File(...),
532 name: str = Form(...),
533 user_api_key_dict: UserAPIKeyAuth = Depends(user_api_key_auth),
534):
535 """
536 Create a character from an uploaded video file.
538 Follows the OpenAI Videos API spec:
539 https://platform.openai.com/docs/api-reference/videos/create-character
541 Example:
542 ```bash
543 curl -X POST "http://localhost:4000/v1/videos/characters" \
544 -H "Authorization: Bearer sk-1234" \
545 -F "video=@character_video.mp4" \
546 -F "name=my_character"
547 ```
548 """
549 from litellm.proxy.proxy_server import (
550 general_settings,
551 llm_router,
552 proxy_config,
553 proxy_logging_obj,
554 select_data_generator,
555 user_api_base,
556 user_max_tokens,
557 user_model,
558 user_request_timeout,
559 user_temperature,
560 version,
561 )
563 data: Final = await _read_request_body(request=request)
564 video_file: Final = await batch_to_bytesio([video])
565 if video_file: 565 ↛ 568line 565 didn't jump to line 568 because the condition on line 565 was always true
566 data["video"] = video_file[0]
568 target_model_name: Final = extract_model_from_target_model_names(data.get("target_model_names"))
569 if target_model_name and not data.get("model"): 569 ↛ 570line 569 didn't jump to line 570 because the condition on line 569 was never true
570 data["model"] = target_model_name
572 custom_llm_provider: Final = (
573 get_custom_llm_provider_from_request_headers(request=request)
574 or get_custom_llm_provider_from_request_query(request=request)
575 or get_custom_provider_from_data(data=data)
576 or "openai"
577 )
578 data["custom_llm_provider"] = custom_llm_provider
580 processor: Final = ProxyBaseLLMRequestProcessing(data=data)
581 try:
582 response: object = await processor.base_process_llm_request(
583 request=request,
584 fastapi_response=fastapi_response,
585 user_api_key_dict=user_api_key_dict,
586 route_type="avideo_create_character",
587 proxy_logging_obj=proxy_logging_obj,
588 llm_router=llm_router,
589 general_settings=general_settings,
590 proxy_config=proxy_config,
591 select_data_generator=select_data_generator,
592 model=None,
593 user_model=user_model,
594 user_temperature=user_temperature,
595 user_request_timeout=user_request_timeout,
596 user_max_tokens=user_max_tokens,
597 user_api_base=user_api_base,
598 version=version,
599 )
600 if target_model_name:
601 hidden_params: Final = getattr(response, "_hidden_params", {}) or {}
602 provider_for_encoding: Final = hidden_params.get("custom_llm_provider") or custom_llm_provider or "openai"
603 model_id_for_encoding: Final = hidden_params.get("model_id") or data.get("model")
604 response = encode_character_id_in_response(
605 response=response,
606 custom_llm_provider=provider_for_encoding,
607 model_id=model_id_for_encoding,
608 )
609 return response
610 except Exception as e:
611 raise await processor._handle_llm_api_exception(
612 e=e,
613 user_api_key_dict=user_api_key_dict,
614 proxy_logging_obj=proxy_logging_obj,
615 version=version,
616 )
619@router.get(
620 "/v1/videos/characters/{character_id}",
621 dependencies=[Depends(user_api_key_auth)],
622 response_class=ORJSONResponse,
623 tags=["videos"],
624)
625@router.get(
626 "/videos/characters/{character_id}",
627 dependencies=[Depends(user_api_key_auth)],
628 response_class=ORJSONResponse,
629 tags=["videos"],
630)
631async def video_get_character(
632 character_id: str,
633 request: Request,
634 fastapi_response: Response,
635 user_api_key_dict: UserAPIKeyAuth = Depends(user_api_key_auth),
636):
637 """
638 Retrieve a character by ID.
640 Follows the OpenAI Videos API spec:
641 https://platform.openai.com/docs/api-reference/videos/get-character
643 Example:
644 ```bash
645 curl -X GET "http://localhost:4000/v1/videos/characters/char_123" \
646 -H "Authorization: Bearer sk-1234"
647 ```
648 """
649 from litellm.proxy.proxy_server import (
650 general_settings,
651 llm_router,
652 proxy_config,
653 proxy_logging_obj,
654 select_data_generator,
655 user_api_base,
656 user_max_tokens,
657 user_model,
658 user_request_timeout,
659 user_temperature,
660 version,
661 )
663 original_requested_character_id: Final = character_id
664 data: Final[dict[str, object]] = {"character_id": character_id}
666 decoded: Final = decode_character_id_with_provider(character_id)
667 provider_from_id: Final = decoded.get("custom_llm_provider")
668 model_id_from_decoded: Final = decoded.get("model_id")
669 decoded_character_id: Final = decoded.get("character_id")
670 if decoded_character_id: 670 ↛ 673line 670 didn't jump to line 673 because the condition on line 670 was always true
671 data["character_id"] = decoded_character_id
673 custom_llm_provider: Final = (
674 get_custom_llm_provider_from_request_headers(request=request)
675 or get_custom_llm_provider_from_request_query(request=request)
676 or await get_custom_llm_provider_from_request_body(request=request)
677 or provider_from_id
678 or "openai"
679 )
680 data["custom_llm_provider"] = custom_llm_provider
682 if model_id_from_decoded and llm_router: 682 ↛ 683line 682 didn't jump to line 683 because the condition on line 682 was never true
683 resolved_model: Final = llm_router.resolve_model_name_from_model_id(model_id_from_decoded)
684 if resolved_model:
685 data["model"] = resolved_model
687 processor: Final = ProxyBaseLLMRequestProcessing(data=data)
688 try:
689 response: object = await processor.base_process_llm_request(
690 request=request,
691 fastapi_response=fastapi_response,
692 user_api_key_dict=user_api_key_dict,
693 route_type="avideo_get_character",
694 proxy_logging_obj=proxy_logging_obj,
695 llm_router=llm_router,
696 general_settings=general_settings,
697 proxy_config=proxy_config,
698 select_data_generator=select_data_generator,
699 model=None,
700 user_model=user_model,
701 user_temperature=user_temperature,
702 user_request_timeout=user_request_timeout,
703 user_max_tokens=user_max_tokens,
704 user_api_base=user_api_base,
705 version=version,
706 )
707 if original_requested_character_id.startswith("character_"):
708 provider_for_encoding: Final = provider_from_id or custom_llm_provider or "openai"
709 model_id_for_encoding: Final = model_id_from_decoded
710 response = encode_character_id_in_response(
711 response=response,
712 custom_llm_provider=provider_for_encoding,
713 model_id=model_id_for_encoding,
714 )
715 return response
716 except Exception as e:
717 raise await processor._handle_llm_api_exception(
718 e=e,
719 user_api_key_dict=user_api_key_dict,
720 proxy_logging_obj=proxy_logging_obj,
721 version=version,
722 )
725@router.post(
726 "/v1/videos/edits",
727 dependencies=[Depends(user_api_key_auth)],
728 response_class=ORJSONResponse,
729 tags=["videos"],
730)
731@router.post(
732 "/videos/edits",
733 dependencies=[Depends(user_api_key_auth)],
734 response_class=ORJSONResponse,
735 tags=["videos"],
736)
737async def video_edit(
738 request: Request,
739 fastapi_response: Response,
740 user_api_key_dict: UserAPIKeyAuth = Depends(user_api_key_auth),
741):
742 """
743 Create a video edit job.
745 Follows the OpenAI Videos API spec:
746 https://platform.openai.com/docs/api-reference/videos/create-edit
748 Example:
749 ```bash
750 curl -X POST "http://localhost:4000/v1/videos/edits" \
751 -H "Authorization: Bearer sk-1234" \
752 -H "Content-Type: application/json" \
753 -d '{"prompt": "Make it brighter", "video": {"id": "video_123"}}'
754 ```
755 """
756 from litellm.proxy.proxy_server import (
757 general_settings,
758 llm_router,
759 proxy_config,
760 proxy_logging_obj,
761 select_data_generator,
762 user_api_base,
763 user_max_tokens,
764 user_model,
765 user_request_timeout,
766 user_temperature,
767 version,
768 )
770 data: Final = await _read_request_body(request=request)
771 uploaded_video: Final = data.pop("video", None)
772 if isinstance(uploaded_video, StarletteUploadFile): 772 ↛ 773line 772 didn't jump to line 773 because the condition on line 772 was never true
773 video_files: Final = await batch_to_bytesio((uploaded_video,))
774 if video_files:
775 data["video"] = video_files[0]
776 data["video_id"] = ""
777 else:
778 data["video_id"] = video_reference_to_id(uploaded_video)
780 decoded: Final = decode_video_id_with_provider(data["video_id"])
781 provider_from_id: Final = decoded.get("custom_llm_provider")
782 model_id_from_decoded: Final = decoded.get("model_id")
784 custom_llm_provider: Final = (
785 get_custom_llm_provider_from_request_headers(request=request)
786 or get_custom_llm_provider_from_request_query(request=request)
787 or get_custom_provider_from_data(data=data)
788 or provider_from_id
789 or "openai"
790 )
791 data["custom_llm_provider"] = custom_llm_provider
793 if model_id_from_decoded and llm_router: 793 ↛ 794line 793 didn't jump to line 794 because the condition on line 793 was never true
794 resolved_model: Final = llm_router.resolve_model_name_from_model_id(model_id_from_decoded)
795 if resolved_model:
796 data["model"] = resolved_model
798 processor: Final = ProxyBaseLLMRequestProcessing(data=data)
799 try:
800 edited: Final[object] = await processor.base_process_llm_request(
801 request=request,
802 fastapi_response=fastapi_response,
803 user_api_key_dict=user_api_key_dict,
804 route_type="avideo_edit",
805 proxy_logging_obj=proxy_logging_obj,
806 llm_router=llm_router,
807 general_settings=general_settings,
808 proxy_config=proxy_config,
809 select_data_generator=select_data_generator,
810 model=None,
811 user_model=user_model,
812 user_temperature=user_temperature,
813 user_request_timeout=user_request_timeout,
814 user_max_tokens=user_max_tokens,
815 user_api_base=user_api_base,
816 version=version,
817 )
818 except Exception as e:
819 raise await processor._handle_llm_api_exception(
820 e=e,
821 user_api_key_dict=user_api_key_dict,
822 proxy_logging_obj=proxy_logging_obj,
823 version=version,
824 )
825 else:
826 return edited
829@router.post(
830 "/v1/videos/extensions",
831 dependencies=[Depends(user_api_key_auth)],
832 response_class=ORJSONResponse,
833 tags=["videos"],
834)
835@router.post(
836 "/videos/extensions",
837 dependencies=[Depends(user_api_key_auth)],
838 response_class=ORJSONResponse,
839 tags=["videos"],
840)
841async def video_extension(
842 request: Request,
843 fastapi_response: Response,
844 user_api_key_dict: UserAPIKeyAuth = Depends(user_api_key_auth),
845):
846 """
847 Create a video extension.
849 Follows the OpenAI Videos API spec:
850 https://platform.openai.com/docs/api-reference/videos/create-extension
852 Example:
853 ```bash
854 curl -X POST "http://localhost:4000/v1/videos/extensions" \
855 -H "Authorization: Bearer sk-1234" \
856 -H "Content-Type: application/json" \
857 -d '{"prompt": "Continue the scene", "seconds": "5", "video": {"id": "video_123"}}'
858 ```
859 """
860 from litellm.proxy.proxy_server import (
861 general_settings,
862 llm_router,
863 proxy_config,
864 proxy_logging_obj,
865 select_data_generator,
866 user_api_base,
867 user_max_tokens,
868 user_model,
869 user_request_timeout,
870 user_temperature,
871 version,
872 )
874 data: Final = await _read_request_body(request=request)
875 data["video_id"] = video_reference_to_id(data.pop("video", None))
877 decoded: Final = decode_video_id_with_provider(data["video_id"])
878 provider_from_id: Final = decoded.get("custom_llm_provider")
879 model_id_from_decoded: Final = decoded.get("model_id")
881 custom_llm_provider: Final = (
882 get_custom_llm_provider_from_request_headers(request=request)
883 or get_custom_llm_provider_from_request_query(request=request)
884 or get_custom_provider_from_data(data=data)
885 or provider_from_id
886 or "openai"
887 )
888 data["custom_llm_provider"] = custom_llm_provider
890 if model_id_from_decoded and llm_router: 890 ↛ 891line 890 didn't jump to line 891 because the condition on line 890 was never true
891 resolved_model: Final = llm_router.resolve_model_name_from_model_id(model_id_from_decoded)
892 if resolved_model:
893 data["model"] = resolved_model
895 processor: Final = ProxyBaseLLMRequestProcessing(data=data)
896 try:
897 extended: Final[object] = await processor.base_process_llm_request(
898 request=request,
899 fastapi_response=fastapi_response,
900 user_api_key_dict=user_api_key_dict,
901 route_type="avideo_extension",
902 proxy_logging_obj=proxy_logging_obj,
903 llm_router=llm_router,
904 general_settings=general_settings,
905 proxy_config=proxy_config,
906 select_data_generator=select_data_generator,
907 model=None,
908 user_model=user_model,
909 user_temperature=user_temperature,
910 user_request_timeout=user_request_timeout,
911 user_max_tokens=user_max_tokens,
912 user_api_base=user_api_base,
913 version=version,
914 )
915 except Exception as e:
916 raise await processor._handle_llm_api_exception(
917 e=e,
918 user_api_key_dict=user_api_key_dict,
919 proxy_logging_obj=proxy_logging_obj,
920 version=version,
921 )
922 else:
923 return extended