C# 使用豆包 AI 模型实现首尾帧模式的视频生成

C# 使用豆包 AI 模型实现首尾帧模式的视频生成

 体验

欲诚其意者,先致其知,致知在格物。人生太多体验,有悲有喜,有好有坏。没有实践就没有发言权,没有亲自尝试就不要轻易否定,适合你的才是最好的。最近在火山引擎火山方舟平台模型广场中看到豆包推出最强视频生成模型 Doubao-Seedance-1.0-pro,于是也想体验一下其魅力如何。模型提供多种生成方式,被其中一项 “首尾帧” 模式所吸引,即提供首图和尾图两张照片,并结合 AI 对话描述生成结果视频。本文则主要讲述如何使用C#调用平台API实现视频生成功能。

调用 API 前需要注册火山引擎帐号并获得 API 开发密钥。

火山引擎注册地址如下:https://console.volcengine.com/auth/login

选择火山方舟 -> API Key 管理 ->  创建 API Key 即可,请注意编辑权限以保证能够调用对应功能的 API 。

构思

如同人与人之间有效的沟通,为 AI 模型提供符合情境的素材,精准、逻辑清晰的对话描述,才能生成符合预期的结果,不过为了测试其 “思考、创意” 能力 ,我提供了两张风马牛不相及的美女图片,简要描述了一下对话,对话内容:“结合图片,请生成类似周杰伦《红颜如霜》的MV,要求生成音乐”。生图照片素材内容如下:

素材图片首帧为有些 “现代风” 的人物座在汽车后排的场景,尾帧是有些 “复古风” 的人物在女生宿舍的场景,看看 AI 模型根据提供的素材会生成什么样的结果视频,期待中还是夹杂着一丝好奇的。

创建视频生成任务

模型 “思考”和生成视频需要一段时间,因此属于异步操作,首先要做的就是向模型申请创建视频生成任务,Doubao_CreateVideo 方法提供了创建视频任务的能力,基本说明如下表:

序号参数名类型说明
1saystring对话描述内容。如“请为我生成一段视频”
2ApiKeystring在火山引擎平台申请的API访问令牌
3first_ImageUrlOrBase64string首帧图片的可访问URL或图片的Base64编码
4last_ImageUrlOrBase64string尾帧图片的可访问URL或图片的Base64编码
5rsstring

指定生成视频的分辨率,默认值为720p

枚举值包括:480p,720p,1080p

6rtstring

指定生成视频的宽高比,默认值为16:9

枚举值包括:16:9,4:3,1:1,3:4,9:16,21:9

7durint

指定生成视频的时长,默认值为 5 秒

最长目前可选择为12秒

8fpsint指定生成视频的帧率,默认值为 24 (fps),
9wmbool指定生成的视频是否包含水印(AI生成字样)
10seedint

种子整数,用于控制生成内容的随机性。默认值为11

11cf=falsebool

是否固定摄像头,默认值为 false。

枚举值:true:固定摄像头。平台会在用户提示词中追加固定摄像头,实际效果不保证。false:不固定摄像头。

12modelstring

使用的模型ID,默认值为官方强烈推荐的 doubao-seedance-1-0-pro-250528。详细 ID 列表请参考官方API文档进行查询。

方法示例代码如下:

string; string; public void Doubao_CreateVideo(string say,string ApiKey,string first_ImageUrlOrBase64,string last_ImageUrlOrBase64 ,string rs="720p",string rt="16:9",int dur=5,int fps=24,bool wm=true,int seed=11,bool cf=false , string model= "doubao-seedance-1-0-pro-250528") { string para = string.Format(" --rs {0} --rt {1} --dur {2} --fps {3} --wm {4} --seed {5} --cf {6}",rs,rt,dur,fps,wm,seed,cf); string ApiUrl = "https://ark.cn-beijing.volces.com/api/v3/contents/generations/tasks"; WebService ws = new WebService(); string[] headers = new string[3]; headers[0] = "Content-Type:application/json"; headers[1] = "Accept:application/json"; headers[2] = "Authorization:Bearer " + ApiKey + ""; StringWriter sw = new StringWriter(); using (Newtonsoft.Json.JsonWriter writer = new Newtonsoft.Json.JsonTextWriter(sw)) { writer.Formatting = Newtonsoft.Json.Formatting.Indented; writer.WriteStartObject(); writer.WritePropertyName("model"); writer.WriteValue(model); writer.WritePropertyName("content"); writer.WriteStartArray(); writer.WriteStartObject(); writer.WritePropertyName("type"); writer.WriteValue("text"); writer.WritePropertyName("text"); writer.WriteValue(say+para); writer.WriteEndObject(); writer.WriteStartObject(); writer.WritePropertyName("type"); writer.WriteValue("image_url"); writer.WritePropertyName("image_url"); writer.WriteStartObject(); writer.WritePropertyName("url"); writer.WriteValue(first_ImageUrlOrBase64); writer.WriteEndObject(); writer.WritePropertyName("role"); writer.WriteValue("first_frame"); writer.WriteEndObject(); writer.WriteStartObject(); writer.WritePropertyName("type"); writer.WriteValue("image_url"); writer.WritePropertyName("image_url"); writer.WriteStartObject(); writer.WritePropertyName("url"); writer.WriteValue(last_ImageUrlOrBase64); writer.WriteEndObject(); writer.WritePropertyName("role"); writer.WriteValue("last_frame"); writer.WriteEndObject(); writer.WriteEndArray(); writer.WriteEndObject(); writer.Flush(); } sw.Close(); string postData = sw.GetStringBuilder().ToString();;; string rs2 = ws.GetResponseResult(ApiUrl, Encoding.UTF8, "POST", postData, headers); ErrorMessage = ws.ErrorMessage; ResultJson = rs2; } 

 其中 WebService 类示例代码如下:

 public sealed class WebService { #region Internal Members public string; #endregion /// <summary> /// 构造函数,提供初始化数据的功能,打开Ftp站点 /// </summary> public string GetResponseResult(string url, System.Text.Encoding encoding, string method, string postData) { return GetResponseResult(url,encoding,method,postData,null); } private static bool validSecurity(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { return true; } public string GetResponseResult(string url, System.Text.Encoding encoding, string method, string postData,string[] headers,string ContentType= "application/x-www-form-urlencoded",bool secValid=true) { method = method.ToUpper(); if (secValid == false) { ServicePointManager.ServerCertificateValidationCallback = validSecurity; } System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Tls | System.Net.SecurityProtocolType.Tls11 | System.Net.SecurityProtocolType.Tls12; if (method == "GET") { try { WebRequest request2 = WebRequest.Create(@url); request2.Method = method; if (headers != null) { for (int i = 0; i < headers.GetLength(0); i++) { if (headers[i].Split(':').Length < 2) { continue; } if (headers[i].Split(':').Length > 1) { if (headers[i].Split(':')[0] == "Content-Type") { request2.ContentType = headers[i].Split(':')[1]; continue; } } request2.Headers.Add(headers[i]); } } WebResponse response2 = request2.GetResponse(); try { Stream stream = response2.GetResponseStream(); StreamReader reader = new StreamReader(stream, encoding); string content2 = reader.ReadToEnd(); return content2; } catch (WebException webEx) { if (webEx.Response is HttpWebResponse errorResponse) { string errorBody; using (Stream stream = errorResponse.GetResponseStream()) using (StreamReader reader = new StreamReader(stream)) { errorBody = reader.ReadToEnd(); } return errorBody; } else { Console.WriteLine($"WebException: {webEx.Message}"); return webEx.Message; } } } catch (Exception ex) { ErrorMessage = ex.Message; return ""; } } if (method == "POST") { Stream outstream = null; Stream instream = null; StreamReader sr = null; HttpWebResponse response = null; HttpWebRequest request = null; byte[] data = encoding.GetBytes(postData); // 准备请求... try { // 设置参数 request = WebRequest.Create(url) as HttpWebRequest; CookieContainer cookieContainer = new CookieContainer(); request.CookieContainer = cookieContainer; request.AllowAutoRedirect = true; request.Method = method; request.Timeout = 1000000; request.ContentType = ContentType; if (headers != null) { for (int i = 0; i < headers.GetLength(0); i++) { if (headers[i].Split(':').Length < 2) { continue; } if (headers[i].Split(':').Length > 1) { if (headers[i].Split(':')[0] == "Host") { request.Host = headers[i].Split(':')[1]; continue; } else if (headers[i].Split(':')[0] == "Content-Type") { request.ContentType = headers[i].Split(':')[1]; continue; } else if (headers[i].Split(':')[0] == "Connection") { request.KeepAlive = headers[i].Split(':')[1] == "close" ? false : true; continue; } else if (headers[i].Split(':')[0] == "Accept") { request.Accept = headers[i].Split(':')[1]; continue; } } request.Headers.Add(headers[i]); } } request.ContentLength = data.Length; try { outstream = request.GetRequestStream(); outstream.Write(data, 0, data.Length); outstream.Close(); //发送请求并获取相应回应数据 response = request.GetResponse() as HttpWebResponse; //直到request.GetResponse()程序才开始向目标网页发送Post请求 instream = response.GetResponseStream(); sr = new StreamReader(instream, encoding); //返回结果网页(html)代码 string content = sr.ReadToEnd(); sr.Close(); sr.Dispose(); return content; } catch (WebException webEx) { if (webEx.Response is HttpWebResponse errorResponse) { string errorBody; using (Stream stream = errorResponse.GetResponseStream()) using (StreamReader reader = new StreamReader(stream)) { errorBody = reader.ReadToEnd(); } return errorBody; } else { Console.WriteLine($"WebException: {webEx.Message}"); return webEx.Message; } } } catch (Exception ex) { ErrorMessage = ex.Message; return ""; } } ErrorMessage = "不正确的方法类型。(目前仅支持GET/POST)"; return ""; }//get response result 

一些基本说明可参考我的文章:https://blog.ZEEKLOG.net/michaelline/article/details/139123272?spm=1011.2415.3001.5331

成功调用会返回如下JSON:

{"id":"cgt-20251000000008-xxxbk"}

其中的 id 就是创建成功后的任务ID,此时模型正在生成视频...

查询视频生成任务

根据创建视频成功后提供的ID,可以通过查询视频生成任务 API,轮询其生成状态,是否完成。Doubao_QueryVideoTask 方法可产现对任务ID的详情查询,基本说明如下表:

序号参数名称参数类型说明
1taskidstring要查询的视频生成任务 ID 字符串
2ApiKeystring在火山引擎平台申请的API访问令牌

方法示例代码如下:

string; string; public void Doubao_QueryVideoTask(string taskid, string ApiKey) { string ApiUrl = "https://ark.cn-beijing.volces.com/api/v3/contents/generations/tasks/" + taskid; WebService ws = new WebService(); string[] headers = new string[2]; headers[0] = "Content-Type:application/json"; headers[1] = "Authorization:Bearer " + ApiKey + "";;; string rs2 = ws.GetResponseResult(ApiUrl, Encoding.UTF8, "GET", "", headers); ErrorMessage = ws.ErrorMessage; ResultJson = rs2; }

成功后会返回如下示例:

{"id":"cgt-2025108-whpbk","model":"doubao-seedance-1-0-pro-250528", "status":"succeeded", "content": {"video_url":"xxx"}, "usage":{"completion_tokens":103818,"total_tokens":103818}, "created_at":1763455989,"updated_at":1763456064, "seed":11, "resolution":"720p", "ratio":"16:9", "duration":5, framespersecond":24}

其中 status 为状态码,succeeded 表示已完成(枚举值包括:queued:排队中、running:任务运行中、cancelled:取消任务,取消状态24h自动删除(只支持排队中状态的任务被取消)、succeeded: 任务成功、failed:任务失败。)。

如果返回JSON中存在 content.video_url 字段的url内容,即可以访问URL或下载播放视频,查看视频生成效果。

查询视频生成任务列表

对于未及时查询单一任务ID的或想查询所有生成中或已完成的视频任务列表,可使用查询视频生成任务列表 API 实现。 该API仅支持查询最近 7 天的历史数据。时间计算统一采用UTC时间戳,返回的7天历史数据范围以用户实际发起批量查询请求的时刻为基准(精确到秒),时间戳区间为 [T-7天, T)。

Doubao_QueryVideoTaskList 方法可产现对任务ID列表的详情查询,基本说明如下表:

序号参数名称参数类型说明
1page_numint

设置查询列表页的起始页码,默认为1,最大为500

2page_sizeint设置查询列表页的每页数量,默认为500,最大为500
3filter_statusstring

视频生成状态的过滤条件,默认为 "succeeded"(成功)

(枚举值包括:queued:排队中、running:任务运行中、cancelled:取消任务,取消状态24h自动删除(只支持排队中状态的任务被取消)、succeeded: 任务成功、failed:任务失败。)

4ApiKeystring在火山引擎平台申请的API访问令牌

方法示例代码如下:

string; string; public void Doubao_QueryVideoTaskList(int page_num=1,int page_size=500,string filter_status= "succeeded",string ApiKey) { string postData = "page_num=" + page_num.ToString() + "&page_size=" + page_size.ToString() + "&filter.status=" + filter_status; string ApiUrl = "https://ark.cn-beijing.volces.com/api/v3/contents/generations/tasks?"+postData; WebService ws = new WebService(); string[] headers = new string[2]; headers[0] = "Content-Type:application/json"; headers[1] = "Authorization:Bearer " + ApiKey + "";;; string rs2 = ws.GetResponseResult(ApiUrl, Encoding.UTF8, "GET", "", headers); ErrorMessage = ws.ErrorMessage; ResultJson = rs2; }

成功调用后会返回如下示例:

{"total":5,"items":[ {"id":"cgt-2025","model":"doubao-seedance-1-0-pro-250528"," status":"succeeded", "content":{"video_url":"https://ark"},"usage":{"completion_tokens":103818,"total_tokens":103818},"created_at":1763455989,"updated_at":1763456064,"seed":11,"resolution":"720p","ratio":"16:9","duration":5,"framespersecond":24}, {"id":"cgt-2025","model":"doubao-seedance-1-0-pro-250528", "status":"succeeded", "content":{"video_url":"https://ark"},"usage":{"completion_tokens":586092,"total_tokens":586092},"created_at":1763082221,"updated_at":1763082414,"seed":26522,"resolution":"1080p","ratio":"3:4","duration":12,"framespersecond":24}, {"id":"cgt-2025","model":"doubao-seedance-1-0-pro-250528", "status":"succeeded", "content":{"video_url":"https://arkt"},"usage":{"completion_tokens":586092,"total_tokens":586092},"created_at":1763082221,"updated_at":1763082446,"seed":81742,"resolution":"1080p","ratio":"3:4","duration":12,"framespersecond":24}, {"id":"cgt-2025","model":"doubao-seedance-1-0-pro-250528", "status":"succeeded", "content":{"video_url":"https://ark-"},"usage":{"completion_tokens":586092,"total_tokens":586092},"created_at":1763082221,"updated_at":1763082376,"seed":46824,"resolution":"1080p","ratio":"3:4","duration":12,"framespersecond":24}, {"id":"cgt-2025","model":"doubao-seedance-1-0-pro-250528", "status":"succeeded", "content":{"video_url":"https://ark"},"usage":{"completion_tokens":586092,"total_tokens":586092},"created_at":1763082221,"updated_at":1763082374,"seed":52271,"resolution":"1080p","ratio":"3:4","duration":12,"framespersecond":24}]}

可通过下列示例代码遍历生成的 videio_url (可访问视频):

string; Newtonsoft.Json.Linq.JObject rs2 = Newtonsoft.Json.Linq.JObject.Parse(ResultJson); for (int i = 0; i < rs2["items"].Count(); i++) { list+ = rs2["items"][i]["content"]["video_url"].ToString() + "\r\n"; }

红颜如霜

生成的视频效果还是有点意思,AI模型还是充分发挥了其想象力,对车辆情况的识别,行走的创意,变化的过度还算可以,毕竟只有12秒的时间。人物面部模型的五官部分稍微显得一点点 “拥挤” 变形,但真实还原度还是非常不错的。另外,要求加入的《红颜如霜》的音乐背景模型没有混入合成,不知是不是因为音乐版权的问题,于是自己录制了一首歌曲片断,使用手机视频编辑软件进行了编辑合成,最终效果如下视频:

AI模型生成的视频

小结

生成视频会消耗很多的 tokens,由于注册的时候使用的先用后付模式,发现体验生成视频模型后,帐户发生欠费,还请注意费用说明及消耗情况,满足自己的需求即可。

API的一些相关文档可以参考以下链接:

文档中心入口:

https://www.volcengine.com/docs/82379

创建视频生成任务 API:

https://www.volcengine.com/docs/82379/1520757

查询视频生成任务 API:

https://www.volcengine.com/docs/82379/1521309

查询视频生成任务列表:

https://www.volcengine.com/docs/82379/1521675

Read more

【Linux】线程池(二)C++ 手写线程池全流程:从核心设计到线程安全、死锁深度解析

【Linux】线程池(二)C++ 手写线程池全流程:从核心设计到线程安全、死锁深度解析

文章目录 * 实现线程池 * ThreadPool类设计 * 构造函数 * Start接口 * 线程池接入日志 * 初步实现源码及效果图 * 总结代码执行逻辑 * 实现回调函数Routine * enqueue接口实现 * 线程池退出stop接口优化 * 线程池源码 * 线程安全和重入问题 * 结论 * 死锁 * 死锁四个必要条件 * 避免死锁 * STL、智能指针和线程安全 实现线程池 我们之前已经接触了进程池,其实线程池和进程池核心思路差不多,对于线程池来说,会有一个任务队列和若干线程,用户往任务队列里添加任务,若干线程在任务队列里拿任务并完成。 ThreadPool类设计 构造函数 对于线程来说,启动线程池分为两步: 1.先创建线程本身(Thread类对象)2.再启动线程(调用Thread的start接口) 所以在构造函数我们要先创建线程本身(thread t(回调函数,线程名)),创建线程需要传递回调函数(假设是hello)和线程名,但这里有一个问题,一般来说传递的

By Ne0inhk
基于飞算JavaAI的在线图书借阅平台设计与实现(深度实践版)

基于飞算JavaAI的在线图书借阅平台设计与实现(深度实践版)

摘要: 本文以从概念到落地,完整构建一个“在线图书借阅平台”的全过程。文章不仅覆盖了环境配置、需求分析、接口设计、数据库建模等基础流程,更着重于展示AI自动生成的项目核心代码,并在此基础上进行了详尽的功能扩展和代码优化。通过对用户管理、图书管理、借阅与归还等关键业务模块的详细代码实现与注释,本文旨在全面、深入地展现飞算JavaAI在真实项目开发中的强大能力,探讨其如何重塑传统Java开发范式,显著提升开发效率与代码质量。 一、引言 在软件工程领域,随着业务逻辑的日益复杂化和市场对产品迭代速度的严苛要求,传统的纯手动编码模式正面临前所未有的挑战。开发周期长、人力成本高、代码质量参差不齐、技术债累积等问题,成为制约项目成功的重要因素。正是在这样的背景下,人工智能辅助编程(AI-Assisted Programming)应运而生,它通过将大型语言模型与软件工程知识深度融合,旨在自动化处理开发流程中的重复性、模式化任务,使开发者能够聚焦于更具创造性的核心业务逻辑。 飞算科技推出的飞算JavaAI,正是这一变革浪潮中的杰出代表。它作为一款深度集成于IntelliJ IDEA的智能插件,能够

By Ne0inhk

Java中使用OKHTTP3的全面教程与实战应用

Java中使用okhttp的全面教程与实战应用 引言:为什么选择okhttp? 在现代Java开发中,进行网络请求是几乎每个项目都不可避免的需求。虽然JDK自带的java.net.HttpURLConnection可以完成基本任务,但它在代码复杂度、功能丰富性和易用性上存在明显短板。这时,okhttp便成为了开发者们的首选。 OKHTTP3是由Square公司开源的一个高性能、易于使用的HTTP客户端库,它不仅提供了简洁的API,还内置了诸多高级特性,如连接池、缓存、拦截器、异步请求等。本教程将带你从零开始,深入掌握okhttp的核心概念与各种应用场景,无论是简单的GET/POST请求,还是复杂的文件上传下载、自定义拦截器、超时控制等,你都能在这里找到清晰的解决方案。 一、环境准备与基础配置 1.1 添加依赖(Maven) 在你的pom.xml文件中添加以下依赖: <dependency><groupId>com.squareup.okhttp3</groupId><artifactId&

By Ne0inhk
Java 大视界 -- Java 大数据机器学习模型在金融产品创新与客户需求匹配中的实战应用(417)

Java 大视界 -- Java 大数据机器学习模型在金融产品创新与客户需求匹配中的实战应用(417)

Java 大视界 -- Java 大数据机器学习模型在金融产品创新与客户需求匹配中的实战应用(417) * 引言:从 3.8% 到 22.5% 的转化率跃升 —— 传统银行的破局之路 * 正文: * 一、传统金融产品模式的 4 大核心痛点(某城商行实战调研) * 二、金融级机器学习架构设计(5 层闭环,满足监管与性能要求) * 架构设计的 3 个金融级原则(区别于互联网场景) * 三、核心模块详解(附完整可运行代码与避坑指南) * 3.1 模块 1:客户画像模型(KMeans + 随机森林,输出 360° 标签) * 3.1.1 画像模型设计(双阶段标签体系) * 3.1.

By Ne0inhk