背景:
我一直打算在使用ASP.NET Core 6.0、C#和ffmpeg的情况下,实现特定视频格式(如“.mkv”、“.wmv”、“.mov”等)的按需转码,以便在一个媒体管理服务器上提供服务。
我的方法:
我采用的方法是动态生成一个.m3u8文件,该文件基于用户选择的片段时长(例如10秒)和已知的视频总时长来创建。以下是我实现这一目标的代码示例,目前暂未考虑分辨率:
public string GenerateVideoOnDemandPlaylist(double duration, int segment)
{
double interval = (double)segment;
var content = new StringBuilder();
content.AppendLine("#EXTM3U");
content.AppendLine("#EXT-X-VERSION:6");
content.AppendLine(String.Format("#EXT-X-TARGETDURATION:{0}", segment));
content.AppendLine("#EXT-X-MEDIA-SEQUENCE:0");
content.AppendLine("#EXT-X-PLAYLIST-TYPE:VOD");
content.AppendLine("#EXT-X-INDEPENDENT-SEGMENTS");
for (double index = 0; (index * interval) < duration; index++)
{
content.AppendLine(String.Format("#EXTINF:{0:#.000000},", ((duration - (index * interval)) > interval) ? interval : ((duration - (index * interval)))));
content.AppendLine(String.Format("{0:00000}.ts", index));
}
content.AppendLine("#EXT-X-ENDLIST");
return content.ToString();
}
[HttpGet]
[Route("stream/{id}/{resolution}.m3u8")]
public IActionResult Stream(string id, string resolution)
{
double duration = RetrieveVideoLengthInSeconds();
return Content(GenerateVideoOnDemandPlaylist(duration, 10), "application/x-mpegURL", Encoding.UTF8);
}
这种方法会生成一个类似下面所示的.m3u8文件:
#EXTM3U
#EXT-X-VERSION:6
#EXT-X-TARGETDURATION:10
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-PLAYLIST-TYPE:VOD
#EXT-X-INDEPENDENT-SEGMENTS
#EXTINF:10.000000,
00000.ts
#EXTINF:3.386667,
00001.ts
#EXT-X-ENDLIST
然后,播放器将请求00000.ts
、00001.ts
等,并由服务器按需生成这些片段:
public byte[] GenerateVideoOnDemandSegment(int index, int duration, string path)
{
// 使用ffmpeg进行按段转码的代码...
}
[HttpGet]
[Route("stream/{id}/{index}.ts")]
public IActionResult Segment(string id, int index)
{
string path = RetrieveVideoPath(id);
return File(GenerateVideoOnDemandSegment(index, 10, path), "application/x-mpegURL", true);
}
问题:
从功能层面看,这个流程可以正常运行,但片段之间的过渡略有瑕疵,特别是在每个10秒标记处,音频会出现短暂中断。如何确保片段之间无缝衔接?在这个过程中有哪些地方可以改进?