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 方法就可以了。
DotNet 使用阿里云媒体转码服务的更多相关文章
- 解决.NET Core中MailKit无法使用阿里云邮件推送服务的问题
在博问中(.net core怎么实现邮件发送)知道了MailKit无法使用阿里云邮件推送服务发送邮件的问题,自已实测也遇到同样的问题,而用自己搭建的邮件服务器没这个问题. 于是,向阿里云提交了工单.. ...
- 阿里云的NoSQL存储服务OTS的应用分析
这篇文章主要介绍了阿里云的NoSQL存储服务OTS的应用分析,OTS作为阿里巴巴开发的NoSQL存储技术服务现已面向用户商业化,需要的朋友可以参考下. 1. 概要 OTS是构建在阿里云飞天分布式系统 ...
- 【阿里云产品公测】在Laravel4框架中使用阿里云ACE的缓存服务
作者:阿里云用户dvbhack 受论坛排版和格式限制,这篇帖子的格式不是很利于阅读,如果你看帖子觉得不那么舒服,可以看我发表在自己博客上的原文:http://www.ofcss.com/2014/04 ...
- wordpress使用阿里云邮件推送服务实现发送邮件
之前用腾迅云时,配置了wordpress是可以使用邮件服务的,然而到了阿里云,却无法使用了,有人说是因为阿里云关了25端口,但腾迅好像也关了. 百度看看有没有其他方法,最终让我找到个方法,可惜不是很完 ...
- Linux通过端口转发来访问内网服务(端口转发访问阿里云Redis数据库等服务)
# 安装rinetd wget http://www.boutell.com/rinetd/http/rinetd.tar.gz&&tar -xvf rinetd.tar.gz& ...
- 阿里云专属推荐码nuyxa6
申请成功!您的推荐码为nuyxa6 恭喜您获得阿里云专属推荐码,推荐码有效期至2017-03-04 14:43:49. 我们会在到期日前两周以站内信的方式通知您新的有效期.
- 阿里云服务器 - node启动服务的时候只有监听内网IP才可以供外网访问
阿里云服务器 - node启动服务的时候只有监听内网IP才可以供外网访问
- 阿里云linux配置ftp服务
阿里云linux配置ftp服务 一.ftp服务安装 运行以下命令安装ftp yum install -y vsftpd 运行以下命令打开及查看etc/vsftpd cd /etc/vsftpd ls ...
- 谷粒 | 10 | 阿里云OSS存储对象服务
阿里云OSS对象存储服务 准备工作 1.在service模块新建子模块service_oss 2.引入pom.xml文件中引入oss服务依赖 <dependencies> <!--a ...
随机推荐
- Python脚本基础运算和算法
原文地址:https://www.cnblogs.com/ailiailan/p/10141741.html 通过关注“常见”脚本,是对代码的一个很好的学习和总结的方式. 1.冒泡排序 lis = [ ...
- typescript属性类型接口
/* typeScript中的接口 - 1.属性类接口 */ /* 接口的作用:在面向对象的编程中,接口是一种规范的定义,它定义了行为和动作的规范,在程序设计里面,接口起到一种限制和规范的作用.接口定 ...
- java-mybaits-014-数据库缓存设计【querycache、mybatis一级缓存、二级缓存】
一.概述 一般来说,可以在5个方面进行缓存的设计: 1.最底层可以配置的是数据库自带的query cache, 2.mybatis的一级缓存,默认情况下都处于开启状态,只能使用自带的Perpetual ...
- mysql quick query row count using sql
1. command show table status like '{table-name}'; 2. sample mysql> use inventory; Database change ...
- Python环境的导入导出
有很多情况下,需要做Python环境的迁移,比如在本地开发环境搭建了某套架构,并安装了需要依赖模块,那么就需要将原有的环境导出到目的机器上,可以使用pip freeze导出. 导出环境,在开发机器上设 ...
- PAT 甲级 1068 Find More Coins (30 分) (dp,01背包问题记录最佳选择方案)***
1068 Find More Coins (30 分) Eva loves to collect coins from all over the universe, including some ...
- Spring MVC 实例:Excel视图的使用
对于Excel而言,Spring MVC所推荐的是使用AbstractXlsView,它实现了视图接口,从其命名也可以知道它只是一个抽象类,不能生成实例对象.它自己定义了一个抽象方法——buildEx ...
- HTML布局排版5 测试某段html页面1
除了div,常见的还有用table布局,这里直接用前面博文的页头页尾,如下面的页面的部分,是个简单的table.该页面样式,如果拖动浏览器,可以看到table和文本框总是居中,但是文本框下方那两个按钮 ...
- 原生JavaScript常用本地浏览器存储方法一(方法类型)
有时需要将网页中的一些数据保存在浏览器端.好处就是当下次访问页面时,直接就可以从本地读取数据,不需要再次向服务器请求数据.目前常用的有以下几种方法: 1.cookie cookie会随着每次HTTP请 ...
- 玩转CONSUL(2)–分布式锁
1. 前言 分布式锁的场景,大家应该都有遇到过.比如对可靠性有较高要求的系统中,我们需要做主备切换.这时我们可以利用分布式锁,来做选主动作,抢到锁作为主,执行对应的任务,剩余的实例作为备份 redis ...