unity 接入火山引擎API,包括即梦AI

风格化图生图

cs 复制代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using System.Security.Cryptography;
using System.Text;
using UnityEngine.Networking;
using Newtonsoft.Json;

//
[Serializable]
public class AlgorithmBaseResp
{
    public int status_code;
    public string status_message;
}
[Serializable]
public class Data
{
    public AlgorithmBaseResp algorithm_base_resp;
    public List<string> binary_data_base64;
    public List<string> image_urls;
}
[Serializable]
public class Result
{
    public int code;
    public Data data;
    public string message;
    public string request_id;
    public int status;
    public string time_elapsed;
}


public class PicToPic : MonoBehaviour
{
    public Result result;

    private static readonly char[] HexDigits = "0123456789ABCDEF".ToCharArray();
    private string _region= "cn-north-1";
    private string _service= "cv";
    private string _schema;
    private string _host= "visual.volcengineapi.com";
    private string _path= "/";
    private string _ak = "替换你自己的Access Key ID";
    private string _sk= "替换你自己的Secret Access Key";

    public string req_key;
    public string sub_req_key;

    public Texture2D texture2D;
    public void SignMenthod(string region, string service, string schema, string host, string path, string ak, string sk)
    {
        _region = region;
        _service = service;
        _schema = schema;
        _host = host;
        _path = path;
        _ak = ak;
        _sk = sk;
    }
    [ContextMenu("StartUpload")]
    public void StartUpload()
    {
        ImgToImg(req_key, sub_req_key);
    }

    public void ImgToImg(string key, string value)
    {
        try
        {
            string filePath = Application.dataPath + "/chooseState/1.png";
           // string baseImage = ImageToBase64(filePath);
            string baseImage = T2dToBase64(texture2D); 

            // 火山官网密钥写入
            string AccessKeyID = _ak;
            string SecretAccessKey = _sk;
            // 请求域名
            string endpoint = "visual.volcengineapi.com";
            string path = "/"; // 路径,不包含 Query// 请求接口信息
            string service = "cv";
            string region = "cn-north-1";
            string schema = "https";
            SignMenthod(region, service, schema, endpoint, path, AccessKeyID, SecretAccessKey);
            // 参考接口文档Query参数
            string action = "CVProcess";
            string version = "2022-08-31";
            DateTime date = DateTime.UtcNow;


            // 参考接口文档Body参数
            var req = new Dictionary<string, object>
            {
                { "req_key", key},
                { "sub_req_key",value},
                { "binary_data_base64", new List<string> { baseImage } },
                { "return_url",true}
            };
            StopCoroutine("DoRequest2");
            StartCoroutine(DoRequest2("POST", new Dictionary<string, string>(), Encoding.UTF8.GetBytes(Newtonsoft.Json.JsonConvert.SerializeObject(req)), date, action, version));
        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
        }
    }


    //public string ImageToBase64(string filepath)
    //{
    //    using (System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(filepath))
    //    {
    //        MemoryStream ms = new MemoryStream();
    //        bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
    //        byte[] arr = new byte[ms.Length];
    //        ms.Position = 0;
    //        ms.Read(arr, 0, (int)ms.Length);
    //        ms.Close();
    //        return Convert.ToBase64String(arr);
    //    }
    //}
    public string T2dToBase64(Texture2D texture2D)
    {
        // 将 Texture2D 编码成 PNG 或 JPG
        byte[] imageBytes = texture2D.EncodeToJPG(100); // 或使用 EncodeToJPG()

        // 转换为 Base64 字符串
        return Convert.ToBase64String(imageBytes);
    }

    public IEnumerator DoRequest2(string method, Dictionary<string, string> queryList, byte[] body,
                          DateTime date, string action, string version)
    {
        if (body == null)
        {
            body = new byte[0];
        }

        string xContentSha256 = HashSHA256(body);
        string xDate = date.ToString("yyyyMMddTHHmmssZ");
        string shortXDate = xDate.Substring(0, 8);
        string contentType = "application/json";
        string signHeader = "host;x-date;x-content-sha256;content-type";

        var realQueryList = new SortedDictionary<string, string>(queryList)
        {
            { "Action", action },
            { "Version", version }
        };

        var queryStringBuilder = new StringBuilder();
        foreach (var kvp in realQueryList)
        {
            queryStringBuilder.Append(UrlEncode(kvp.Key))
                              .Append("=")
                              .Append(UrlEncode(kvp.Value))
                              .Append("&");
        }

        queryStringBuilder.Length--; // Remove the last '&'

        string canonicalStringBuilder = $"{method}\n{_path}\n{queryStringBuilder}\n" +
                                        $"host:{_host}\n" +
                                        $"x-date:{xDate}\n" +
                                        $"x-content-sha256:{xContentSha256}\n" +
                                        $"content-type:{contentType}\n" +
                                        "\n" +
                                        $"{signHeader}\n" +
                                        $"{xContentSha256}";

        Debug.Log(canonicalStringBuilder);

        string hashCanonicalString = HashSHA256(Encoding.UTF8.GetBytes(canonicalStringBuilder));
        string credentialScope = $"{shortXDate}/{_region}/{_service}/request";
        string signString = $"HMAC-SHA256\n{xDate}\n{credentialScope}\n{hashCanonicalString}";

        byte[] signKey = GenSigningSecretKeyV4(_sk, shortXDate, _region, _service);
        string signature = BitConverter.ToString(HmacSHA256(signKey, signString)).Replace("-", "").ToLower();

        var url = $"{_schema}://{_host}{_path}?{queryStringBuilder}";
        url = "https://visual.volcengineapi.com?Action=CVProcess&Version=2022-08-31";

        using (UnityWebRequest webRequest = new UnityWebRequest(url, "POST"))
        {
            // 设置请求内容
            webRequest.uploadHandler = (UploadHandler)new UploadHandlerRaw(body);
            webRequest.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer();
            webRequest.SetRequestHeader("Content-Type", "application/json");
            webRequest.SetRequestHeader("Host", _host);
            webRequest.SetRequestHeader("X-Date", xDate);
            webRequest.SetRequestHeader("X-Content-Sha256", xContentSha256);
            webRequest.SetRequestHeader("Authorization",
                $"HMAC-SHA256 Credential={_ak}/{credentialScope}, SignedHeaders={signHeader}, Signature={signature}");

            yield return webRequest.SendWebRequest();
            if (webRequest.result != UnityWebRequest.Result.ConnectionError || webRequest.result != UnityWebRequest.Result.ProtocolError)
            {
                try
                {
                    string responseText = webRequest.downloadHandler.text;

                    Debug.Log(responseText);
                    //print(responseText);
                    result = JsonConvert.DeserializeObject<Result>(responseText);
                    //Data.Binarycount = result.data.binary_data_base64;
                    //Base64ToSave(result.data.binary_data_base64[0], null);
                    //显示以及后续处理                 
                }
                catch (Exception ex)
                {
                    Debug.Log($"发送失败:{ex.Message}");
                }
            }
            else
            {
                //失败提示处理
            }
            webRequest.Dispose();

        }
    }


    //public void Base64ToSave(string base64, Action<Bitmap> action)
    //{
    //    try
    //    {
    //        string imgPath = $"{Application.dataPath}\\saveImg\\" + "XXX.png";
    //        string imgeName = DateTime.Now.ToString("hh_mm_ss") + ".png";
    //        byte[] bytes = Convert.FromBase64String(base64);
    //        using (MemoryStream mStream = new MemoryStream(bytes))
    //        {
    //            System.Drawing.Image mImage = System.Drawing.Image.FromStream(mStream);
    //            Bitmap bmp = new Bitmap(mImage);
    //            bmp.Save(imgPath, System.Drawing.Imaging.ImageFormat.Png);
    //            action((Bitmap)bmp.Clone());
    //            bmp.Dispose();
    //            mImage.Dispose();
    //        }
    //    }
    //    catch (Exception ex)
    //    {
    //        Debug.Log($"保存图片出现异常:{ex.Message}");
    //    }
    //}

    private string UrlEncode(string source)
    {
        if (string.IsNullOrEmpty(source))
        {
            return source;
        }

        var encoded = new StringBuilder(source.Length);
        foreach (var symbol in Encoding.UTF8.GetBytes(source))
        {
            if (symbol >= 97 && symbol <= 122 || symbol >= 65 && symbol <= 90 || symbol >= 48 && symbol <= 57 ||
                symbol == (byte)'-' || symbol == (byte)'_' || symbol == (byte)'.' || symbol == (byte)'~')
            {
                encoded.Append((char)symbol);
            }
            else if (symbol == 32)
            {
                encoded.Append("%20");
            }
            else
            {
                encoded.Append('%');
                encoded.Append(HexDigits[symbol >> 4]);
                encoded.Append(HexDigits[symbol & 15]);
            }
        }

        return encoded.ToString();
    }

    public static string HashSHA256(byte[] content)
    {
        using (SHA256 sha256 = SHA256.Create())
        {
            byte[] hash = sha256.ComputeHash(content);
            return BitConverter.ToString(hash).Replace("-", "").ToLower();
        }
    }

    public static byte[] HmacSHA256(byte[] key, string content)
    {
        using (HMACSHA256 hmac = new HMACSHA256(key))
        {
            return hmac.ComputeHash(Encoding.UTF8.GetBytes(content));
        }
    }

    private byte[] GenSigningSecretKeyV4(string secretKey, string date, string region, string service)
    {
        byte[] kDate = HmacSHA256(Encoding.UTF8.GetBytes(secretKey), date);
        byte[] kRegion = HmacSHA256(kDate, region);
        byte[] kService = HmacSHA256(kRegion, service);
        return HmacSHA256(kService, "request");
    }
}

即梦AI图生图

cs 复制代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using System.Security.Cryptography;
using System.Text;
using UnityEngine.Networking;
using Newtonsoft.Json;


[Serializable]
public class JMData
{
    public List<string> PreviewImage_121;
    public AlgorithmBaseResp algorithm_base_resp;
    public List<object> binary_data_base64;
    public double comfyui_cost;
    public List<string> image_urls;
}
[Serializable]
public class JMResult
{
    public int code;
    public JMData data;
    public string message;
    public string request_id;
    public int status;
    public string time_elapsed;
}


public class JMAI : MonoBehaviour
{
    public JMResult result;

    private static readonly char[] HexDigits = "0123456789ABCDEF".ToCharArray();
    private string _region = "cn-north-1";
    private string _service = "cv";
    private string _schema;
    private string _host = "visual.volcengineapi.com";
    private string _path = "/";
    private string _ak = "替换你自己的Access Key ID";
    private string _sk= "替换你自己的Secret Access Key";

    public string prompt;

    public Texture2D texture2D;
    public void SignMenthod(string region, string service, string schema, string host, string path, string ak, string sk)
    {
        _region = region;
        _service = service;
        _schema = schema;
        _host = host;
        _path = path;
        _ak = ak;
        _sk = sk;
    }
    [ContextMenu("StartUpload")]
    public void StartUpload()
    {
        ImgToImg(prompt);
    }

    public void ImgToImg(string prompt)
    {
        try
        {
            string filePath = Application.dataPath + "/chooseState/1.png";
            // string baseImage = ImageToBase64(filePath);
            string baseImage = T2dToBase64(texture2D);

            // 火山官网密钥写入
            string AccessKeyID = _ak;
            string SecretAccessKey = _sk;
            // 请求域名
            string endpoint = "visual.volcengineapi.com";
            string path = "/"; // 路径,不包含 Query// 请求接口信息
            string service = "cv";
            string region = "cn-north-1";
            string schema = "https";
            SignMenthod(region, service, schema, endpoint, path, AccessKeyID, SecretAccessKey);
            // 参考接口文档Query参数
            string action = "CVProcess";
            string version = "2022-08-31";
            DateTime date = DateTime.UtcNow;


            // 参考接口文档Body参数
            var req = new Dictionary<string, object>
            {
                { "req_key", "jimeng_i2i_v30"},
                { "prompt",prompt},
                { "binary_data_base64", new List<string> { baseImage } },
                { "return_url",true}
            };
            StopCoroutine("DoRequest2");
            StartCoroutine(DoRequest2("POST", new Dictionary<string, string>(), Encoding.UTF8.GetBytes(Newtonsoft.Json.JsonConvert.SerializeObject(req)), date, action, version));
        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
        }
    }


    //public string ImageToBase64(string filepath)
    //{
    //    using (System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(filepath))
    //    {
    //        MemoryStream ms = new MemoryStream();
    //        bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
    //        byte[] arr = new byte[ms.Length];
    //        ms.Position = 0;
    //        ms.Read(arr, 0, (int)ms.Length);
    //        ms.Close();
    //        return Convert.ToBase64String(arr);
    //    }
    //}
    public string T2dToBase64(Texture2D texture2D)
    {
        // 将 Texture2D 编码成 PNG 或 JPG
        byte[] imageBytes = texture2D.EncodeToJPG(100); // 或使用 EncodeToJPG()

        // 转换为 Base64 字符串
        return Convert.ToBase64String(imageBytes);
    }

    public IEnumerator DoRequest2(string method, Dictionary<string, string> queryList, byte[] body,
                          DateTime date, string action, string version)
    {
        if (body == null)
        {
            body = new byte[0];
        }

        string xContentSha256 = HashSHA256(body);
        string xDate = date.ToString("yyyyMMddTHHmmssZ");
        string shortXDate = xDate.Substring(0, 8);
        string contentType = "application/json";
        string signHeader = "host;x-date;x-content-sha256;content-type";

        var realQueryList = new SortedDictionary<string, string>(queryList)
        {
            { "Action", action },
            { "Version", version }
        };

        var queryStringBuilder = new StringBuilder();
        foreach (var kvp in realQueryList)
        {
            queryStringBuilder.Append(UrlEncode(kvp.Key))
                              .Append("=")
                              .Append(UrlEncode(kvp.Value))
                              .Append("&");
        }

        queryStringBuilder.Length--; // Remove the last '&'

        string canonicalStringBuilder = $"{method}\n{_path}\n{queryStringBuilder}\n" +
                                        $"host:{_host}\n" +
                                        $"x-date:{xDate}\n" +
                                        $"x-content-sha256:{xContentSha256}\n" +
                                        $"content-type:{contentType}\n" +
                                        "\n" +
                                        $"{signHeader}\n" +
                                        $"{xContentSha256}";

        Debug.Log(canonicalStringBuilder);

        string hashCanonicalString = HashSHA256(Encoding.UTF8.GetBytes(canonicalStringBuilder));
        string credentialScope = $"{shortXDate}/{_region}/{_service}/request";
        string signString = $"HMAC-SHA256\n{xDate}\n{credentialScope}\n{hashCanonicalString}";

        byte[] signKey = GenSigningSecretKeyV4(_sk, shortXDate, _region, _service);
        string signature = BitConverter.ToString(HmacSHA256(signKey, signString)).Replace("-", "").ToLower();

        var url = $"{_schema}://{_host}{_path}?{queryStringBuilder}";
        url = "https://visual.volcengineapi.com?Action=CVProcess&Version=2022-08-31";

        using (UnityWebRequest webRequest = new UnityWebRequest(url, "POST"))
        {
            // 设置请求内容
            webRequest.uploadHandler = (UploadHandler)new UploadHandlerRaw(body);
            webRequest.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer();
            webRequest.SetRequestHeader("Content-Type", "application/json");
            webRequest.SetRequestHeader("Host", _host);
            webRequest.SetRequestHeader("X-Date", xDate);
            webRequest.SetRequestHeader("X-Content-Sha256", xContentSha256);
            webRequest.SetRequestHeader("Authorization",
                $"HMAC-SHA256 Credential={_ak}/{credentialScope}, SignedHeaders={signHeader}, Signature={signature}");

            yield return webRequest.SendWebRequest();
            if (webRequest.result != UnityWebRequest.Result.ConnectionError || webRequest.result != UnityWebRequest.Result.ProtocolError)
            {
                try
                {
                    string responseText = webRequest.downloadHandler.text;

                    Debug.Log(responseText);
                    //print(responseText);
                    result = JsonConvert.DeserializeObject<JMResult>(responseText);
                    //Data.Binarycount = result.data.binary_data_base64;
                    //Base64ToSave(result.data.binary_data_base64[0], null);
                    //显示以及后续处理                 
                }
                catch (Exception ex)
                {
                    Debug.Log($"发送失败:{ex.Message}");
                }
            }
            else
            {
                //失败提示处理
            }
            webRequest.Dispose();

        }
    }


    //public void Base64ToSave(string base64, Action<Bitmap> action)
    //{
    //    try
    //    {
    //        string imgPath = $"{Application.dataPath}\\saveImg\\" + "XXX.png";
    //        string imgeName = DateTime.Now.ToString("hh_mm_ss") + ".png";
    //        byte[] bytes = Convert.FromBase64String(base64);
    //        using (MemoryStream mStream = new MemoryStream(bytes))
    //        {
    //            System.Drawing.Image mImage = System.Drawing.Image.FromStream(mStream);
    //            Bitmap bmp = new Bitmap(mImage);
    //            bmp.Save(imgPath, System.Drawing.Imaging.ImageFormat.Png);
    //            action((Bitmap)bmp.Clone());
    //            bmp.Dispose();
    //            mImage.Dispose();
    //        }
    //    }
    //    catch (Exception ex)
    //    {
    //        Debug.Log($"保存图片出现异常:{ex.Message}");
    //    }
    //}

    private string UrlEncode(string source)
    {
        if (string.IsNullOrEmpty(source))
        {
            return source;
        }

        var encoded = new StringBuilder(source.Length);
        foreach (var symbol in Encoding.UTF8.GetBytes(source))
        {
            if (symbol >= 97 && symbol <= 122 || symbol >= 65 && symbol <= 90 || symbol >= 48 && symbol <= 57 ||
                symbol == (byte)'-' || symbol == (byte)'_' || symbol == (byte)'.' || symbol == (byte)'~')
            {
                encoded.Append((char)symbol);
            }
            else if (symbol == 32)
            {
                encoded.Append("%20");
            }
            else
            {
                encoded.Append('%');
                encoded.Append(HexDigits[symbol >> 4]);
                encoded.Append(HexDigits[symbol & 15]);
            }
        }

        return encoded.ToString();
    }

    public static string HashSHA256(byte[] content)
    {
        using (SHA256 sha256 = SHA256.Create())
        {
            byte[] hash = sha256.ComputeHash(content);
            return BitConverter.ToString(hash).Replace("-", "").ToLower();
        }
    }

    public static byte[] HmacSHA256(byte[] key, string content)
    {
        using (HMACSHA256 hmac = new HMACSHA256(key))
        {
            return hmac.ComputeHash(Encoding.UTF8.GetBytes(content));
        }
    }

    private byte[] GenSigningSecretKeyV4(string secretKey, string date, string region, string service)
    {
        byte[] kDate = HmacSHA256(Encoding.UTF8.GetBytes(secretKey), date);
        byte[] kRegion = HmacSHA256(kDate, region);
        byte[] kService = HmacSHA256(kRegion, service);
        return HmacSHA256(kService, "request");
    }
}

即梦图生视频

cs 复制代码
using Newtonsoft.Json;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Security.Cryptography;
using System.Text;
using UnityEngine;
using UnityEngine.Networking;
[Serializable]
public class JMVideoData
{
    public List<object> binary_data_base64 ;
    public object image_urls ;
    public string resp_data ;
    public string status ;
    public string video_url ;
}
[Serializable]
public class JMVideoResult
{
    public int code ;
    public JMVideoData data ;
    public string message ;
    public string request_id ;
    public int status ;
    public string time_elapsed ;
}
public class JMVideo : MonoBehaviour
{
    public JMVideoResult result;

    private static readonly char[] HexDigits = "0123456789ABCDEF".ToCharArray();
    private string _region = "cn-north-1";
    private string _service = "cv";
    private string _schema;
    private string _host = "visual.volcengineapi.com";
    private string _path = "/";
    private string _ak = "替换你自己的Access Key ID";
    private string _sk= "替换你自己的Secret Access Key";

    public string prompt;

    public Texture2D texture2D;

    public string taskId;

    public void SignMenthod(string region, string service, string schema, string host, string path, string ak, string sk)
    {
        _region = region;
        _service = service;
        _schema = schema;
        _host = host;
        _path = path;
        _ak = ak;
        _sk = sk;
    }
    [ContextMenu("StartUpload")]
    public void StartUpload()
    {
        ImgToImg(prompt);
    }
    [ContextMenu("CheckTask")]
    public void CheckTask()
    {
        try
        {
            // 火山官网密钥写入
            string AccessKeyID = _ak;
            string SecretAccessKey = _sk;
            // 请求域名
            string endpoint = "visual.volcengineapi.com";
            string path = "/"; // 路径,不包含 Query// 请求接口信息
            string service = "cv";
            string region = "cn-north-1";
            string schema = "https";
            SignMenthod(region, service, schema, endpoint, path, AccessKeyID, SecretAccessKey);
            // 参考接口文档Query参数
            string action = "CVSync2AsyncGetResult";
            string version = "2022-08-31";
            DateTime date = DateTime.UtcNow;


            // 参考接口文档Body参数
            var req = new Dictionary<string, object>
            {
                { "req_key", "jimeng_vgfm_i2v_l20"},
                { "task_id",taskId}
            };
            StopCoroutine("DoRequest2");
            StartCoroutine(DoRequest2("POST", new Dictionary<string, string>(), Encoding.UTF8.GetBytes(Newtonsoft.Json.JsonConvert.SerializeObject(req)), date, action, version));
        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
        }
    }


    public void ImgToImg(string prompt)
    {
        try
        {
            //string filePath = Application.dataPath + "/chooseState/1.png";
            // string baseImage = ImageToBase64(filePath);
            string baseImage = T2dToBase64(texture2D);

            // 火山官网密钥写入
            string AccessKeyID = _ak;
            string SecretAccessKey = _sk;
            // 请求域名
            string endpoint = "visual.volcengineapi.com";
            string path = "/"; // 路径,不包含 Query// 请求接口信息
            string service = "cv";
            string region = "cn-north-1";
            string schema = "https";
            SignMenthod(region, service, schema, endpoint, path, AccessKeyID, SecretAccessKey);
            // 参考接口文档Query参数
            string action = "CVSync2AsyncSubmitTask";
            string version = "2022-08-31";
            DateTime date = DateTime.UtcNow;


            // 参考接口文档Body参数
            var req = new Dictionary<string, object>
            {
                { "req_key", "jimeng_vgfm_i2v_l20"},
                { "prompt",prompt},
                { "binary_data_base64", new List<string> { baseImage } },
                { "aspect_ratio","16:9"}
            };
            StopCoroutine("DoRequest2");
            StartCoroutine(DoRequest2("POST", new Dictionary<string, string>(), Encoding.UTF8.GetBytes(Newtonsoft.Json.JsonConvert.SerializeObject(req)), date, action, version));
        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
        }
    }


    //public string ImageToBase64(string filepath)
    //{
    //    using (System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(filepath))
    //    {
    //        MemoryStream ms = new MemoryStream();
    //        bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
    //        byte[] arr = new byte[ms.Length];
    //        ms.Position = 0;
    //        ms.Read(arr, 0, (int)ms.Length);
    //        ms.Close();
    //        return Convert.ToBase64String(arr);
    //    }
    //}
    public string T2dToBase64(Texture2D texture2D)
    {
        // 将 Texture2D 编码成 PNG 或 JPG
        byte[] imageBytes = texture2D.EncodeToJPG(100); // 或使用 EncodeToJPG()

        // 转换为 Base64 字符串
        return Convert.ToBase64String(imageBytes);
    }

    public IEnumerator DoRequest2(string method, Dictionary<string, string> queryList, byte[] body,
                          DateTime date, string action, string version)
    {
        if (body == null)
        {
            body = new byte[0];
        }

        string xContentSha256 = HashSHA256(body);
        string xDate = date.ToString("yyyyMMddTHHmmssZ");
        string shortXDate = xDate.Substring(0, 8);
        string contentType = "application/json";
        string signHeader = "host;x-date;x-content-sha256;content-type";

        var realQueryList = new SortedDictionary<string, string>(queryList)
        {
            { "Action", action },
            { "Version", version }
        };

        var queryStringBuilder = new StringBuilder();
        foreach (var kvp in realQueryList)
        {
            queryStringBuilder.Append(UrlEncode(kvp.Key))
                              .Append("=")
                              .Append(UrlEncode(kvp.Value))
                              .Append("&");
        }

        queryStringBuilder.Length--; // Remove the last '&'

        string canonicalStringBuilder = $"{method}\n{_path}\n{queryStringBuilder}\n" +
                                        $"host:{_host}\n" +
                                        $"x-date:{xDate}\n" +
                                        $"x-content-sha256:{xContentSha256}\n" +
                                        $"content-type:{contentType}\n" +
                                        "\n" +
                                        $"{signHeader}\n" +
                                        $"{xContentSha256}";

        Debug.Log(canonicalStringBuilder);

        string hashCanonicalString = HashSHA256(Encoding.UTF8.GetBytes(canonicalStringBuilder));
        string credentialScope = $"{shortXDate}/{_region}/{_service}/request";
        string signString = $"HMAC-SHA256\n{xDate}\n{credentialScope}\n{hashCanonicalString}";

        byte[] signKey = GenSigningSecretKeyV4(_sk, shortXDate, _region, _service);
        string signature = BitConverter.ToString(HmacSHA256(signKey, signString)).Replace("-", "").ToLower();

        var url = $"{_schema}://{_host}{_path}?{queryStringBuilder}";
        url = "https://visual.volcengineapi.com?Action="+action+"&Version=2022-08-31";

        using (UnityWebRequest webRequest = new UnityWebRequest(url, "POST"))
        {
            // 设置请求内容
            webRequest.uploadHandler = (UploadHandler)new UploadHandlerRaw(body);
            webRequest.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer();
            webRequest.SetRequestHeader("Content-Type", "application/json");
            webRequest.SetRequestHeader("Host", _host);
            webRequest.SetRequestHeader("X-Date", xDate);
            webRequest.SetRequestHeader("X-Content-Sha256", xContentSha256);
            webRequest.SetRequestHeader("Authorization",
                $"HMAC-SHA256 Credential={_ak}/{credentialScope}, SignedHeaders={signHeader}, Signature={signature}");

            yield return webRequest.SendWebRequest();
            if (webRequest.result != UnityWebRequest.Result.ConnectionError || webRequest.result != UnityWebRequest.Result.ProtocolError)
            {
                try
                {
                    string responseText = webRequest.downloadHandler.text;

                    Debug.Log(responseText);
                  
                   // result = JsonConvert.DeserializeObject<JMVideoResult>(responseText);
                               
                }
                catch (Exception ex)
                {
                    Debug.Log($"发送失败:{ex.Message}");
                }
            }
            else
            {
                //失败提示处理
            }
            webRequest.Dispose();

        }
    }

  
    //public void Base64ToSave(string base64, Action<Bitmap> action)
    //{
    //    try
    //    {
    //        string imgPath = $"{Application.dataPath}\\saveImg\\" + "XXX.png";
    //        string imgeName = DateTime.Now.ToString("hh_mm_ss") + ".png";
    //        byte[] bytes = Convert.FromBase64String(base64);
    //        using (MemoryStream mStream = new MemoryStream(bytes))
    //        {
    //            System.Drawing.Image mImage = System.Drawing.Image.FromStream(mStream);
    //            Bitmap bmp = new Bitmap(mImage);
    //            bmp.Save(imgPath, System.Drawing.Imaging.ImageFormat.Png);
    //            action((Bitmap)bmp.Clone());
    //            bmp.Dispose();
    //            mImage.Dispose();
    //        }
    //    }
    //    catch (Exception ex)
    //    {
    //        Debug.Log($"保存图片出现异常:{ex.Message}");
    //    }
    //}

    private string UrlEncode(string source)
    {
        if (string.IsNullOrEmpty(source))
        {
            return source;
        }

        var encoded = new StringBuilder(source.Length);
        foreach (var symbol in Encoding.UTF8.GetBytes(source))
        {
            if (symbol >= 97 && symbol <= 122 || symbol >= 65 && symbol <= 90 || symbol >= 48 && symbol <= 57 ||
                symbol == (byte)'-' || symbol == (byte)'_' || symbol == (byte)'.' || symbol == (byte)'~')
            {
                encoded.Append((char)symbol);
            }
            else if (symbol == 32)
            {
                encoded.Append("%20");
            }
            else
            {
                encoded.Append('%');
                encoded.Append(HexDigits[symbol >> 4]);
                encoded.Append(HexDigits[symbol & 15]);
            }
        }

        return encoded.ToString();
    }

    public static string HashSHA256(byte[] content)
    {
        using (SHA256 sha256 = SHA256.Create())
        {
            byte[] hash = sha256.ComputeHash(content);
            return BitConverter.ToString(hash).Replace("-", "").ToLower();
        }
    }

    public static byte[] HmacSHA256(byte[] key, string content)
    {
        using (HMACSHA256 hmac = new HMACSHA256(key))
        {
            return hmac.ComputeHash(Encoding.UTF8.GetBytes(content));
        }
    }

    private byte[] GenSigningSecretKeyV4(string secretKey, string date, string region, string service)
    {
        byte[] kDate = HmacSHA256(Encoding.UTF8.GetBytes(secretKey), date);
        byte[] kRegion = HmacSHA256(kDate, region);
        byte[] kService = HmacSHA256(kRegion, service);
        return HmacSHA256(kService, "request");
    }
}
相关推荐
美酒没故事°1 天前
Open WebUI安装指南。搭建自己的自托管 AI 平台
人工智能·windows·ai
鸿乃江边鸟1 天前
Nanobot 从onboard启动命令来看个人助理Agent的实现
人工智能·ai
本旺1 天前
【Openclaw 】完美解决 Codex 认证失败
ai·codex·openclaw·小龙虾·gpt5.4
张張4081 天前
(域格)环境搭建和编译
c语言·开发语言·python·ai
黄思搏1 天前
基于标注平台数据的 Unity UI 自动化构建工作流设计与工程实践
ui·unity·蓝湖·vectoui
乐鑫科技 Espressif1 天前
使用 MCP 服务器,把乐鑫文档接入 AI 工作流
人工智能·ai·esp32·乐鑫科技
语戚1 天前
Stable Diffusion 入门:架构、空间与生成流程概览
人工智能·ai·stable diffusion·aigc·模型
俊哥V1 天前
每日 AI 研究简报 · 2026-04-08
人工智能·ai
一个欠登儿程序员1 天前
在国产服务器上通过 Docker 部署 Windows 虚拟机
服务器·windows·docker
rrrjqy1 天前
什么是RAG?
ai