zoukankan      html  css  js  c++  java
  • DotNet 使用阿里云媒体转码服务

    公司项目中一部分文件放到了阿里云 OSS 上,其中有些音频文件是 amr 类型的,在后期使用的时候比较麻烦,所以需要转换成 mp3 的文件,方便以后使用。本来想使用 ffmpeg 处理,但由于文件都存放在阿里云 OSS 上,使用 ffmpeg 就需要把文件从远程下载下来,转码之后再重新传回阿里云上,还需要使用消息组件进行通知,而且转码对服务器的压力也会很大。不如直接使用阿里云的媒体转码服务来的快,阿里云只提供了 OSS 的 DotNet 类库,并没有提供 MTS 的,所以只能自己参考 API 和其他语言的类库来开发,还好 MTS 的 API 并不是很复杂,几次尝试之后就搞定了。

    相关参数需要从阿里云的控制台获取。

    阿里云媒体转码服务类:

       /// <summary>
        /// 阿里云媒体转码服务助手类。
        /// </summary>
        public class MediaTranscodeHelper
        {
    
            private static readonly Encoding ENCODE_TYPE = Encoding.UTF8;
            private static readonly string ALGORITHM = "HmacSHA1";
            private static readonly string HTTP_METHOD = "GET";
            private static readonly string SEPARATOR = "&";
            private static readonly string EQUAL = "=";
            private static readonly string ISO8601_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'";
            private static readonly string RegionId = "cn-beijing";
            private static readonly string Version = "2014-06-18";
            private static readonly string Action = "SubmitJobs";
            private static readonly string Format = "JSON";
            private static readonly string MtsDomain = "mts.cn-beijing.aliyuncs.com";
    
    
            private static readonly int MaxRetryNumber = 3;
            private static readonly bool AutoRetry = true;
            private static readonly int TimeoutInMilliSeconds = 100000;
    
    
            private static readonly string AccessKeyId = "you AccessKeyId";
            private static readonly string AccessKeySecret = "you AccessKeySecret";
            private static readonly string PipelineId = "you PipelineId";
    
    
            /// <summary>
            /// 提交转码任务。
            /// </summary>
            /// <param name="inputFile">输入文件。</param>
            /// <returns>输出文件。</returns>
            public static string SubmitTranscodeJob(string inputFile, string ossLocation)
            {
                string outputJob = string.Empty;
    
                return outputJob;
            }
    
            /// <summary>
            /// 提交转码任务。
            /// </summary>
            public async Task<(bool success, string response)> SubmitTranscodeJob()
            {
                string SignatureNonce = Guid.NewGuid().ToString();
                var paramers = new Dictionary<string, string>
                {
                    { "Action", Action },
                    { "Version", "2014-06-18" },
                    { "AccessKeyId", AccessKeyId },
                    { "Timestamp", FormatIso8601Date(DateTime.Now) },
                    { "SignatureMethod", "HMAC-SHA1" },
                    { "SignatureVersion", "1.0" },
                    { "SignatureNonce", SignatureNonce },
                    { "Format", Format },
                    { "PipelineId", PipelineId },
                    { "Input", "{"Bucket":"charlesbeijng","Location":"oss-cn-beijing","Object":"3.amr"}" },
                    { "OutputBucket", "charlesbeijng" },
                    { "OutputLocation", "oss-cn-beijing" },
                    { "Outputs", " [{"OutputObject":"" + Guid.NewGuid().ToString() + ".mp3","TemplateId":"1a94dc364cec44708f00367938a0122f","Location":"oss-cn-beijing","WaterMarks":[{"InputFile":{"Bucket":"charlesbeijng","Location":"oss-cn-beijing","Object":"1.png"},"WaterMarkTemplateId":"c473de87d0504f44be7ebdac1667ab13"}]}]" }
                };
    
                try
                {
                    string url = GetSignUrl(paramers, AccessKeySecret);
    
                    int retryTimes = 1;
                    var reply = await HttpGetAsync(url);
                    while (500 <= reply.StatusCode && AutoRetry && retryTimes < MaxRetryNumber)
                    {
                        url = GetSignUrl(paramers, AccessKeySecret);
                        reply = await HttpGetAsync(url);
                        retryTimes++;
                    }
    
                    if (!string.IsNullOrEmpty(reply.response))
                    {
                        var res = JsonConvert.DeserializeObject<Dictionary<string, string>>(reply.response);
                        if (res != null && res.ContainsKey("Code") && "OK".Equals(res["Code"]))
                        {
                            return (true, reply.response);
                        }
                    }
    
                    return (false, reply.response);
                }
                catch (Exception ex)
                {
                    return (false, response: ex.Message);
                }
            }
    
            /// <summary>
            /// 同步请求。
            /// </summary>
            /// <param name="url"></param>
            /// <returns></returns>
            private static string HttpGet(string url)
            {
                HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
                req.Method = HTTP_METHOD;
                req.KeepAlive = true;
                req.UserAgent = "idui1";
                req.Timeout = TimeoutInMilliSeconds;
                req.ContentType = "application/x-www-form-urlencoded;charset=utf-8";
                HttpWebResponse rsp = null;
                try
                {
                    rsp = (HttpWebResponse)req.GetResponse();
                }
                catch (WebException webEx)
                {
                    if (webEx.Status == WebExceptionStatus.Timeout)
                    {
                        rsp.Close();
                    }
                }
    
                if (rsp != null)
                {
                    if (rsp.CharacterSet != null)
                    {
                        Encoding encoding = Encoding.GetEncoding(rsp.CharacterSet);
                        return GetResponseAsString(rsp, encoding);
                    }
                    else
                    {
                        return string.Empty;
                    }
                }
                else
                {
                    return string.Empty;
                }
            }
    
            /// <summary>
            /// 异步请求。
            /// </summary>
            /// <param name="url"></param>
            /// <returns></returns>
            private async Task<(int StatusCode, string response)> HttpGetAsync(string url)
            {
                HttpClientHandler handler = new HttpClientHandler();
                handler.Proxy = null;
                handler.AutomaticDecompression = DecompressionMethods.GZip;
    
                using (var http = new HttpClient(handler))
                {
                    http.Timeout = new TimeSpan(TimeSpan.TicksPerMillisecond * TimeoutInMilliSeconds);
                    HttpResponseMessage response = await http.GetAsync(url);
                    return ((int)response.StatusCode, await response.Content.ReadAsStringAsync());
                }
            }
    
            /// <summary>
            /// 把响应流转换为文本。
            /// </summary>
            /// <param name="rsp">响应流对象</param>
            /// <param name="encoding">编码方式</param>
            /// <returns>响应文本</returns>
            private static string GetResponseAsString(HttpWebResponse rsp, Encoding encoding)
            {
                StringBuilder result = new StringBuilder();
                Stream stream = null;
                StreamReader reader = null;
    
                try
                {
    
                    // 以字符流的方式读取HTTP响应
                    stream = rsp.GetResponseStream();
                    //rsp.Close();
                    reader = new StreamReader(stream, encoding);
    
                    // 每次读取不大于256个字符,并写入字符串
                    char[] buffer = new char[256];
                    int readBytes = 0;
                    while ((readBytes = reader.Read(buffer, 0, buffer.Length)) > 0)
                    {
                        result.Append(buffer, 0, readBytes);
                    }
                }
                catch (WebException webEx)
                {
                    if (webEx.Status == WebExceptionStatus.Timeout)
                    {
                        result = new StringBuilder();
                    }
                }
                finally
                {
                    // 释放资源
                    if (reader != null) reader.Close();
                    if (stream != null) stream.Close();
                    if (rsp != null) rsp.Close();
                }
    
                return result.ToString();
            }
    
            /// <summary>
            /// 处理消息。
            /// </summary>
            /// <param name="message">消息内容。</param>
            public static void HandlingMessage(string message)
            {
    
            }
    
            /// <summary>
            /// 
            /// </summary>
            /// <param name="dateTime"></param>
            /// <returns></returns>
            private static string FormatIso8601Date(DateTime dateTime)
            {
                return dateTime.ToUniversalTime().ToString("yyyy-MM-dd'T'HH:mm:ss'Z'", CultureInfo.CreateSpecificCulture("en-US"));
            }
    
    
            /// <summary>
            /// 签名
            /// </summary>
            public static string SignString(string source, string accessSecret)
            {
                using (var algorithm = new HMACSHA1(Encoding.UTF8.GetBytes(accessSecret.ToCharArray())))
                {
                    return Convert.ToBase64String(algorithm.ComputeHash(Encoding.UTF8.GetBytes(source.ToCharArray())));
                }
            }
    
    
            private string GetSignUrl(Dictionary<string, string> parameters, string accessSecret)
            {
                var imutableMap = new Dictionary<string, string>(parameters)
                {
                    //{ "Timestamp", FormatIso8601Date(DateTime.Now) },
                    //{ "SignatureMethod", "HMAC-SHA1" },
                    //{ "SignatureVersion", "1.0" },
                    //{ "SignatureNonce", Guid.NewGuid().ToString() },
                    //{ "Action", Action },
                    //{ "Version", Version },
                    //{ "Format", Format },
                    //{ "RegionId", RegionId }
                };
    
                IDictionary<string, string> sortedDictionary = new SortedDictionary<string, string>(imutableMap, StringComparer.Ordinal);
                StringBuilder canonicalizedQueryString = new StringBuilder();
                foreach (var p in sortedDictionary)
                {
                    canonicalizedQueryString.Append("&")
                    .Append(PercentEncode(p.Key)).Append("=")
                    .Append(PercentEncode(p.Value));
                }
    
                StringBuilder stringToSign = new StringBuilder();
                stringToSign.Append(HTTP_METHOD);
                stringToSign.Append(SEPARATOR);
                stringToSign.Append(PercentEncode("/"));
                stringToSign.Append(SEPARATOR);
                stringToSign.Append(PercentEncode(canonicalizedQueryString.ToString().Substring(1)));
    
                string signature = SignString(stringToSign.ToString(), accessSecret + "&");
    
                imutableMap.Add("Signature", signature);
    
                return ComposeUrl(MtsDomain, imutableMap);
            }
            private static string ComposeUrl(string endpoint, Dictionary<String, String> parameters)
            {
                StringBuilder urlBuilder = new StringBuilder("");
                urlBuilder.Append("http://").Append(endpoint);
                if (-1 == urlBuilder.ToString().IndexOf("?"))
                {
                    urlBuilder.Append("/?");
                }
                string query = ConcatQueryString(parameters);
                return urlBuilder.Append(query).ToString();
            }
            private static string ConcatQueryString(Dictionary<string, string> parameters)
            {
                if (null == parameters)
                {
                    return null;
                }
                StringBuilder sb = new StringBuilder();
    
                foreach (var entry in parameters)
                {
                    String key = entry.Key;
                    String val = entry.Value;
    
                    sb.Append(HttpUtility.UrlEncode(key, Encoding.UTF8));
                    if (val != null)
                    {
                        sb.Append("=").Append(HttpUtility.UrlEncode(val, Encoding.UTF8));
                    }
                    sb.Append("&");
                }
    
                int strIndex = sb.Length;
                if (parameters.Count > 0)
                    sb.Remove(strIndex - 1, 1);
    
                return sb.ToString();
            }
    
            public static string PercentEncode(string value)
            {
                StringBuilder stringBuilder = new StringBuilder();
                string text = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~";
                byte[] bytes = Encoding.GetEncoding("UTF-8").GetBytes(value);
                foreach (char c in bytes)
                {
                    if (text.IndexOf(c) >= 0)
                    {
                        stringBuilder.Append(c);
                    }
                    else
                    {
                        stringBuilder.Append("%").Append(
                            string.Format(CultureInfo.InvariantCulture, "{0:X2}", (int)c));
                    }
                }
                return stringBuilder.ToString();
            }
            /// <summary>
            /// HMAC-SHA1加密算法
            /// </summary>
            /// <param name="key">密钥</param>
            /// <param name="input">要加密的串</param>
            /// <returns></returns>
            public static string HmacSha1(string key, string input)
            {
                byte[] keyBytes = Encoding.UTF8.GetBytes(key);
                byte[] inputBytes = Encoding.UTF8.GetBytes(input);
                HMACSHA1 hmac = new HMACSHA1(keyBytes);
                byte[] hashBytes = hmac.ComputeHash(inputBytes);
                return Convert.ToBase64String(hashBytes);
            }
            /// <summary>
            /// AES 算法加密(ECB模式) 将明文加密,加密后进行base64编码,返回密文
            /// </summary>
            /// <param name="EncryptStr">明文</param>
            /// <param name="Key">密钥</param>
            /// <returns>加密后base64编码的密文</returns>
            public static string Encrypt(string EncryptStr, string Key)
            {
                try
                {
                    //byte[] keyArray = Encoding.UTF8.GetBytes(Key);
                    byte[] keyArray = Convert.FromBase64String(Key);
                    byte[] toEncryptArray = Encoding.UTF8.GetBytes(EncryptStr);
    
                    RijndaelManaged rDel = new RijndaelManaged
                    {
                        Key = keyArray,
                        Mode = CipherMode.ECB,
                        Padding = PaddingMode.PKCS7
                    };
    
                    ICryptoTransform cTransform = rDel.CreateEncryptor();
                    byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
    
                    return Convert.ToBase64String(resultArray, 0, resultArray.Length);
                }
                catch (Exception)
                {
                    return null;
                }
            }
    
            public static string Decrypt(string toDecrypt, string key)
            {
                byte[] keyArray = Convert.FromBase64String(key); // 将 TestGenAESByteKey 类输出的字符串转为 byte 数组
                byte[] toEncryptArray = Convert.FromBase64String(toDecrypt);
                RijndaelManaged rDel = new RijndaelManaged
                {
                    Key = keyArray,
                    Mode = CipherMode.ECB,        // 必须设置为 ECB
                    Padding = PaddingMode.PKCS7  // 必须设置为 PKCS7
                };
                ICryptoTransform cTransform = rDel.CreateDecryptor();
                byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
                return Encoding.UTF8.GetString(resultArray);
            }
            private static string BuildCanonicalizedQueryString(Dictionary<string, string> parameters)
            {
                // 对参数进行排序
                List<string> sortedKeys = new List<string>(parameters.Keys);
                sortedKeys.Sort();
    
                StringBuilder temp = new StringBuilder();
    
                foreach (var key in sortedKeys)
                {
                    // 此处需要对 key 和 value 进行编码
                    string value = parameters[key];
                    temp.Append(SEPARATOR).Append(PercentEncode(key)).Append(EQUAL).Append(PercentEncode(value));
                }
                return temp.ToString().Substring(1);
            }
    
    
            private static string BuildRequestURL(string signature, Dictionary<string, string> parameters)
            {
                // 生成请求 URL
                StringBuilder temp = new StringBuilder("mts.cn-beijing.aliyuncs.com");
                temp.Append(HttpUtility.UrlEncode("Signature", ENCODE_TYPE)).Append("=").Append(signature);
                foreach (var item in parameters)
                {
                    temp.Append("&").Append(PercentEncode(item.Key)).Append("=").Append(PercentEncode(item.Value));
                }
                return temp.ToString();
            }
        }
    

    使用的时候直接调用 SubmitTranscodeJob 方法就可以了。

  • 相关阅读:
    jquery事件优化---事件委托
    2017年7月6号,总结所遇到的问题
    js日期函数
    跨域请求所遇到的错误
    ajax设置Access-Control-Allow-Origin实现跨域访问
    php提前输出响应及注意问题
    php中的日期和时间
    跨域请求json数据
    C++ 与 Visual Studio 2019 和 WSL(四)——库组件
    fpic 和 fPIC
  • 原文地址:https://www.cnblogs.com/weisenz/p/11308806.html
Copyright © 2011-2022 走看看