|
| 1 | +import http.client |
| 2 | +import json |
| 3 | +import time |
| 4 | + |
| 5 | +class KlingTextToVideo: |
| 6 | + def __init__(self, api_token, api_url): |
| 7 | + """初始化 Kling 视频生成器 |
| 8 | + |
| 9 | + 参数: |
| 10 | + api_token: API 密钥 |
| 11 | + api_url: API 节点地址 |
| 12 | + """ |
| 13 | + self.api_url = api_url |
| 14 | + self.api_token = api_token |
| 15 | + # 初始化 HTTP 连接 |
| 16 | + self.conn = http.client.HTTPSConnection(self.api_url) |
| 17 | + self.endpoint = "/kling/v1/videos/text2video" |
| 18 | + # 设置请求头 |
| 19 | + self.headers = { |
| 20 | + 'Authorization': f'Bearer {self.api_token}', |
| 21 | + 'Content-Type': 'application/json' |
| 22 | + } |
| 23 | + |
| 24 | + def _kling_generate_video(self, model_name, prompt, negative_prompt="", cfg_scale=0.5, |
| 25 | + mode="std", aspect_ratio="16:9", duration="5", |
| 26 | + camera_control=None, callback_url="", external_task_id=""): |
| 27 | + """使用 kling 生成视频 |
| 28 | + |
| 29 | + 参数: |
| 30 | + model_name: str, 模型名称 可选择 kling-v1-6 或 kling-v1 |
| 31 | + prompt: str, 文本提示词 |
| 32 | + negative_prompt: str, 负向文本提示词 |
| 33 | + cfg_scale: float, 生成视频的自由度,取值范围:[0, 1] |
| 34 | + mode: str, 生成模式:std(标准模式) 或 pro(专家模式) |
| 35 | + aspect_ratio: str, 视频比例:16:9, 9:16, 1:1 |
| 36 | + duration: str, 视频时长(秒):5 或 10 |
| 37 | + camera_control: dict, 摄像机控制参数 |
| 38 | + callback_url: str, 回调地址,可以用于 webhook 等通知场景 |
| 39 | + external_task_id: str, 自定义任务ID |
| 40 | + 返回参数: |
| 41 | + task_id: 生成任务的 id |
| 42 | + """ |
| 43 | + # 构建请求体,请求的核心参数 |
| 44 | + payload_dict = { |
| 45 | + "model_name": model_name, |
| 46 | + "prompt": prompt, |
| 47 | + "negative_prompt": negative_prompt, |
| 48 | + "cfg_scale": cfg_scale, |
| 49 | + "mode": mode, |
| 50 | + "aspect_ratio": aspect_ratio, |
| 51 | + "duration": duration, |
| 52 | + "callback_url": callback_url, |
| 53 | + "external_task_id": external_task_id |
| 54 | + } |
| 55 | + |
| 56 | + # 如果提供了摄像机控制参数,添加到请求体中 |
| 57 | + if camera_control: |
| 58 | + payload_dict["camera_control"] = camera_control |
| 59 | + |
| 60 | + payload = json.dumps(payload_dict) |
| 61 | + |
| 62 | + # 发送 POST 请求,提交视频生成任务 |
| 63 | + self.conn.request("POST", self.endpoint, payload, self.headers) |
| 64 | + # 获取响应 |
| 65 | + res = self.conn.getresponse() |
| 66 | + # 读取响应内容并解析为 JSON |
| 67 | + json_data = json.loads(res.read().decode("utf-8")) |
| 68 | + # print(json_data) |
| 69 | + # 检查响应是否成功 |
| 70 | + if 'code' in json_data and json_data['code'] == 0: |
| 71 | + # 成功则返回提交的任务 id |
| 72 | + return json_data['data']['task_id'] |
| 73 | + else: |
| 74 | + # 失败则返回错误信息 |
| 75 | + raise Exception(f"API调用失败:{json_data['message']}") |
| 76 | + |
| 77 | + def _query_kling_video_url(self, task_id): |
| 78 | + """使用查询接口获取生成视频 url |
| 79 | + |
| 80 | + 输入参数: |
| 81 | + task_id: 生成任务的 id |
| 82 | + 输出参数: |
| 83 | + video_url: 视频 url |
| 84 | + """ |
| 85 | + # 构建查询路径 |
| 86 | + query_path = f"{self.endpoint}/{task_id}" |
| 87 | + |
| 88 | + # 发送 GET 请求,查询视频生成任务状态 |
| 89 | + self.conn.request("GET", query_path, None, self.headers) |
| 90 | + # 获取响应 |
| 91 | + res = self.conn.getresponse() |
| 92 | + # 读取响应内容并解析为 JSON |
| 93 | + json_data = json.loads(res.read().decode("utf-8")) |
| 94 | + |
| 95 | + # 检查响应是否成功 |
| 96 | + if json_data['code'] == 0: |
| 97 | + # 如果任务状态为成功,则返回视频 url |
| 98 | + if json_data['data']['task_status'] == "succeed": |
| 99 | + video_url = json_data['data']['task_result']['videos'][0]['url'] |
| 100 | + video_id = json_data['data']['task_result']['videos'][0]['id'] |
| 101 | + return video_url, video_id |
| 102 | + else: |
| 103 | + return None |
| 104 | + else: |
| 105 | + # 如果查询失败,抛出异常 |
| 106 | + raise Exception(f"视频状态查询失败: {json_data['message']}") |
| 107 | + |
| 108 | + def generate_video(self, model_name, prompt, negative_prompt="", cfg_scale=0.5, |
| 109 | + mode="std", aspect_ratio="16:9", duration="5", |
| 110 | + camera_control=None, callback_url="", external_task_id="", timeout=600): |
| 111 | + """实现功能,直接根据预设的参数返回生成视频的 url |
| 112 | + |
| 113 | + 参数: |
| 114 | + model_name: str, 模型名称 可选择 kling-v1-6 或 kling-v1 |
| 115 | + prompt: str, 文本提示词 |
| 116 | + negative_prompt: str, 负向文本提示词 |
| 117 | + cfg_scale: float, 生成视频的自由度,取值范围:[0, 1] |
| 118 | + mode: str, 生成模式:std(标准模式) 或 pro(专家模式) |
| 119 | + aspect_ratio: str, 视频比例:16:9, 9:16, 1:1 |
| 120 | + duration: str, 视频时长(秒):5 或 10 |
| 121 | + camera_control: dict, 摄像机控制参数 |
| 122 | + callback_url: str, 回调地址,可以用于 webhook 等通知场景 |
| 123 | + external_task_id: str, 自定义任务ID |
| 124 | + timeout: int, 超时时间(秒) |
| 125 | + 返回参数: |
| 126 | + video_url: 视频 url |
| 127 | + """ |
| 128 | + # 调用生成视频 api 提交视频生成任务,返回获取 task_id |
| 129 | + task_id = self._kling_generate_video( |
| 130 | + model_name, prompt, negative_prompt, cfg_scale, |
| 131 | + mode, aspect_ratio, duration, camera_control, |
| 132 | + callback_url, external_task_id |
| 133 | + ) |
| 134 | + |
| 135 | + start_time = time.time() |
| 136 | + # 轮询等待生成完成 |
| 137 | + while True: |
| 138 | + # 根据 task_id 调用查询视频 api 查看视频生成任务是否完成 |
| 139 | + video_url, video_id = self._query_kling_video_url(task_id) |
| 140 | + # 如果视频生成任务完成,则返回视频 url |
| 141 | + if video_url is not None: |
| 142 | + return video_url, video_id |
| 143 | + # 如果轮询超时,则返回 None |
| 144 | + if time.time() - start_time > timeout: |
| 145 | + print(f"请求达到 {timeout} 秒超时") |
| 146 | + return None |
| 147 | + # 轮询间隔 3 秒(视频生成通常需要更长时间) |
| 148 | + time.sleep(3) |
| 149 | + print(f"等待视频生成,{int(time.time() - start_time)} 秒", flush=True) |
| 150 | + |
| 151 | + |
| 152 | +# 使用示例 |
| 153 | +if __name__ == "__main__": |
| 154 | + API_URL = "www.dmxapi.cn" # API 节点地址 |
| 155 | + DMX_API_TOKEN = "sk-XXXXXXXXXXXXX" # API 密钥 |
| 156 | + |
| 157 | + # 创建视频生成器实例 |
| 158 | + kling_text_to_video = KlingTextToVideo(api_token=DMX_API_TOKEN, api_url=API_URL) |
| 159 | + |
| 160 | + # 示例摄像机控制 |
| 161 | + # camera_control = { |
| 162 | + # "type": "down_back", # 预定义运镜类型 可选 “simple”, “down_back”, “forward_up”, “right_turn_forward”, “left_turn_forward” |
| 163 | + # # 如果使用 simple 类型,需要配置以下参数(六选一) |
| 164 | + # # "config": { |
| 165 | + # # "horizontal": 0, # 水平运镜 [-10, 10] |
| 166 | + # # "vertical": 0, # 垂直运镜 [-10, 10] |
| 167 | + # # "pan": 5, # 水平摇镜 [-10, 10] |
| 168 | + # # "tilt": 0, # 垂直摇镜 [-10, 10] |
| 169 | + # # "roll": 0, # 旋转运镜 [-10, 10] |
| 170 | + # # "zoom": 0 # 变焦 [-10, 10] |
| 171 | + # # } |
| 172 | + # } |
| 173 | + |
| 174 | + # 生成视频 |
| 175 | + video_url, video_id = kling_text_to_video.generate_video( |
| 176 | + model_name="kling-v1", # [必选]模型名称 可选择 kling-v1-6 或 kling-v1 |
| 177 | + prompt="一只可爱的卡通袋鼠,举起了一个写着 DMXAPI 的牌子", # [必选]文本提示词 |
| 178 | + # negative_prompt="模糊, 扭曲", # 负向文本提示词 |
| 179 | + # cfg_scale=0.5, # 生成视频的自由度 可选 [0,1] |
| 180 | + # mode="std", # 生成模式 可选 std(标准模式) 或 pro(专家模式) |
| 181 | + # aspect_ratio="16:9", # 视频比例 可选 16:9, 9:16, 1:1 |
| 182 | + # duration="5", # 视频时长(秒) 可选 5 或 10 |
| 183 | + # camera_control=camera_control, # 摄像机控制 配置见上 |
| 184 | + # callback_url="", # 回调地址 |
| 185 | + # external_task_id="", # 自定义任务ID |
| 186 | + # timeout=600 # 轮询等待超时时间(秒) |
| 187 | + ) |
| 188 | + |
| 189 | + print(video_url) |
| 190 | + print(video_id) |
0 commit comments