一.视频切片
/// <summary>
/// 视频切片代码
/// </summary>
/// <param name="ffmpegfile"> ffmpeg路径 </param>
/// <param name="sourceFile"> 待切片源文件路径</param>
/// <param name="m3U8File"> 待生成m3u8文件路径</param>
/// <param name="tsFile">待生成ts文件路径</param>
/// <returns>返回m3u8文件路径</returns>
public static async Task<string> Conver2M3u8(string ffmpegfile, string sourceFile, string m3U8File, string tsFile)
{
Task<string> task = new Task<string>(() =>
{
var command =
$@" -i {sourceFile} -codec copy -vbsf h264_mp4toannexb -map 0 -f segment -segment_list {m3U8File} -segment_time 10 {tsFile}/out%03d.ts";
using (System.Diagnostics.Process ffmpeg = new System.Diagnostics.Process())
{
ffmpeg.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
ffmpeg.StartInfo.FileName = ffmpegfile;
ffmpeg.StartInfo.Arguments = command;
ffmpeg.StartInfo.UseShellExecute = false;
ffmpeg.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
ffmpeg.StartInfo.RedirectStandardError = true;
try
{
ffmpeg.Start();
ffmpeg.WaitForExit();
return m3U8File;
}
catch (Exception e)
{
throw e;
}
}
});
return await task;
}
二.修改M3U8文件
/// <summary>
/// 因为ffmpeg 文件生成的m3u8指向的是本地路径 所以修改M3u8文件指向网络路径
/// </summary>
/// <param name="filePath">M3u8文件路径</param>
/// <param name="key">需要加的验证信息</param>
/// <param name="url">网络路径</param>
/// <returns>返回重新生成好的m3u8 字符串</returns>
private string CreateMeta(string filePath,string key,string url)
{
if (System.IO.File.Exists(filePath))
{
using (var fs = System.IO.File.OpenText(filePath))
{
StringBuilder sb = new StringBuilder(fs.ReadToEnd());
sb.Replace("output", $@"{url}?id=out");
sb.Replace(".ts", $@"&key={key}&type=.ts");
return sb.ToString();
}
}
return null;
}
三. 读取/播放 Action
public async Task<ActionResult> PlayerSource(string id, string key)
{
var filePath = $@"D:\work\DJOASystem\DJOASyetemMvc\test\video\{id}.ts";
Response.AddHeader("Access-Control-Allow-Origin", "*");
Response.AddHeader("Access-Control-Allow-Methods", "GET");
using (var fs = System.IO.File.Open(filePath,FileMode.Open,FileAccess.Read,FileShare.ReadWrite))
{
byte[] buffer = new byte[fs.Length];
await fs.ReadAsync(buffer,0,(int)fs.Length);
return new FileContentResult(buffer, "video/MP2T");
}
}
public ActionResult PlayerMeta(string id)
{
var filePath = @"D:\video\playlist.m3u8";
Response.AddHeader("Access-Control-Allow-Origin", "*");
Response.AddHeader("Access-Control-Allow-Methods", "GET");
var fileString = CreateMeta(filePath);
byte[] byteArray = System.Text.Encoding.Default.GetBytes(fileString);
return new FileContentResult(byteArray, "application/vnd.apple.mpegurl");
}
四.遇到问题
-
开始使用Response.Flush 写入bytes,发现手机端无法播放,报错 断开连接…后修改为返回FileContentResult 让MVC自己处理各种头
-
前端的话 用videoJs+videojs-contrib-hls就可以
-
未来可以考虑m3u8 AES加密 更严密