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");
    }
}
相关推荐
带刺的坐椅37 分钟前
Claude Code Skills,Google A2A Skills,Solon AI Skills 有什么区别?
java·ai·solon·a2a·claudecode·skills
南宫乘风40 分钟前
Claude Code 从 0 到 1 实战全攻略:掌握下一代编程 Agent 的核心能力
ai·claude·mcp
仙剑魔尊重楼43 分钟前
音乐制作电子软件FL Studio2025.2.4.5242中文版新功能介绍
windows·音频·录屏·音乐·fl studio
PHP小志1 小时前
Windows 服务器怎么修改密码和用户名?账户被系统锁定如何解锁
windows
CBeann1 小时前
企业级规则引擎落地实战:动态脚本引擎 QLExpress ,真香!
java·ai·大模型·规则引擎·qlexpress·大厂实战项目
Thexhy2 小时前
Ollama 指南
ai·大模型
在路上看风景2 小时前
31. Unity 异步加载的底层细节
unity
水中加点糖2 小时前
小白都能看懂的——车牌检测与识别(最新版YOLO26快速入门)
人工智能·yolo·目标检测·计算机视觉·ai·车牌识别·lprnet
专注VB编程开发20年2 小时前
vb.net datatable新增数据时改用数组缓存
java·linux·windows
仙剑魔尊重楼3 小时前
专业音乐制作软件fl Studio 2025.2.4.5242中文版新功能
windows·音乐·fl studio