您现在的位置是:网站首页>编程语言

怎么撸一个m3u8视频下载程序(提升篇)

编程语言阿文2020年3月12日5387浏览

简介在上一篇中我们讲了m3u8视频下载基本逻辑,现在我们对那段代码进行几点优化。优化点:1.m3u8文件下载成功了但是部分视频片段ts下载失败了,视频ts在下载过程中因……

        在上一篇《怎么撸一个m3u8视频下载程序(基础篇)》中我们讲了m3u8视频下载基本逻辑,现在我们对那段代码进行几点优化。

优化点:

        1.m3u8文件下载成功了但是部分视频片段ts下载失败了,视频ts在下载过程中因为网络问题视频文件下载失败怎处理

        2.下载下来的视频片段ts文件怎么知道是内容格式正确(本地能打开播放的文件)

        3.下载好的视频片段ts怎么命名(下面会详解)

        4.下载好的视频片段ts怎么自动合并成一个文件

        5.最重要的一点,程序猿不应该忘记的一点:日志!日志!日志!

大概流程图:

l2

优化方案:

m3u8文件下载成功了但是部分视频片段ts下载失败了,视频ts在下载过程中因为网络问题视频文件下载失败怎处理

         首先m3u8文件已经下载成功了,我们可以省去再次下载m3u8的操作

                    if (!File.Exists(filesavedic + @"/" + m3u8filename))
                    {
                        if (!DownloadFile(m3u8url, filesavedic + @"/" + m3u8filename))
                        {
                            Log.Error("下载m3u8文件失败:" + m3u8url);
                            return false;
                        }
                    }

        视频片段ts文件也可以这样处理,本地存在要下载的ts文件就跳过,只下载不存在视频

                            if (File.Exists(tsfilepath))
                            {
                                continue;
                            }

         其次我本地创建了3个文件夹来区分原始下载的文件、下载后检验成功的文件以及视频下载完成合并成功的文件,其中原始文件目录用来和m3u8文件里面的ts文件名对比来判断哪些文件未下载。    

            var savesoucepath = basesavepath + @"/souce"; //原始文件目录
            var savemergepath = basesavepath + @"/merge"; //ts合并文件目录
            var savesuccesspath = basesavepath + @"/success"; //ts合并成功目录

下载下来的视频片段ts文件怎么知道是内容格式正确(本地能打开播放的文件)

        我们怎么知道一个视频ts文件是否正确能打开,其实ts文件有一个编码规范(我也是百度来的) 其中一个就是文件的长度跟188取模等于0,这样我们可以判断本地的ts文件是不是内容格式正确,也可以防止部分视频平台因为下载速度太快反爬虫机制给输出一个不完整的文件流(这里防止不住部分平台就给一个长度正确的错误文件流,ts文件本地播放不了)

                            if (File.Exists(tsfilepath))
                            {
                                var filelength = File.ReadAllBytes(tsfilepath).Length;
                                if (filelength % 188 == 0)
                                {
                                    successcount++;
                                    continue;
                                }
                            }
                            //下载ts文件
                            if (DownloadFile(tsurl, tsfilepath))
                            {
                                var filelength = File.ReadAllBytes(tsfilepath).Length;
                                if (filelength % 188 == 0)
                                {
                                    successcount++;
                                    var filemergepath = savemergepath + @"/" + xdirname + @"/" + Common.GetSystemSortName(currnum) + ".ts";
                                    File.Copy(tsfilepath, filemergepath, true);
                                }
                                else
                                {
                                    Log.Error("下载ts文件校验不合法:" + tsurl);
                                }
                            }
                            else
                            {
                                Log.Error("下载ts文件失败:" + tsurl);
                            }

下载好的视频片段ts怎么命名

        可能平时下载文件时都没注意排序可以按照修改时间来展示之类的,但是在dos里面显示文件顺序总体的排序规则都是遵循二进制码。

xa734

         遇到a1.ts、a2.ts、a3.ts....a12.ts、a13.ts .....a20.ts 时会成a1.ts、a11.ts....a2.ts、a20.ts这样的排序,具体原因在cmd命令行无损合并批处理TS视频文件 这篇文件中合并ts文件时会遇到合并后的视频内容错乱。我自己做了一个命名处理,序号为1位数前面+a ,两位数前面+b ,三位数前面+c ,这样排序先按照字母排序 然后按照数字排序能准确得到文件排序。

            /// <summary>
            /// 根据文件数字序号获取系统文件默认排序命名
            /// </summary>
            /// <param name="num"></param>
            /// <returns></returns>
            static public string GetSystemSortName(int num)
            {
                string[] arr = { "a", "b", "c", "d", "e", "f", "g", "h" }; //暂时只支持8位数  够用了,一般一个视频的ts个数也没有8位数的
                var numlength = num.ToString().Length;
                if (numlength > arr.Length)
                    return "";
                return arr[numlength - 1] + num.ToString();
            }

下载好的视频片段ts怎么自动合并成一个文件

         下载好的视频片段ts合并成一个文件,我们可以在程序里面调用cmd命令

                if (!Directory.Exists(savesuccesspath))
                    Directory.CreateDirectory(savesuccesspath);
                var cmdsavemergepath = savemergepath.Replace(@"/", @"\");
                var cmdsavesuccesspath = savesuccesspath.Replace(@"/", @"\");
                var cmddic = cmdsavemergepath + @"\" + savedirname;
                //string str = "copy /b  " + cmddic + @"\" + "*.ts  " + cmdsavesuccesspath + @"\" + savedirname + ".ts";
                string str = "copy /b  " + cmddic + @"\" + "*.ts  " + cmdsavesuccesspath + @"\" + savedirname + ".mp4";
                System.Diagnostics.Process p = new System.Diagnostics.Process();
                p.StartInfo.FileName = "cmd.exe";
                p.StartInfo.Arguments = "cd " + cmdsavemergepath + @"\" + savedirname;
                p.StartInfo.UseShellExecute = false;    //是否使用操作系统shell启动
                p.StartInfo.RedirectStandardInput = true;//接受来自调用程序的输入信息
                p.StartInfo.RedirectStandardOutput = true;//由调用程序获取输出信息
                p.StartInfo.RedirectStandardError = true;//重定向标准错误输出
                p.StartInfo.CreateNoWindow = true;//不显示程序窗口
                p.Start();//启动程序
                //向cmd窗口发送输入信息
                p.StandardInput.WriteLine(str + "&exit");
                p.StandardInput.AutoFlush = true;
                //p.StandardInput.WriteLine("exit");
                //向标准输入写入要执行的命令。这里使用&是批处理命令的符号,表示前面一个命令不管是否执行成功都执行后面(exit)命令,如果不执行exit命令,后面调用ReadToEnd()方法会假死
                //同类的符号还有&&和||前者表示必须前一个命令执行成功才会执行后面的命令,后者表示必须前一个命令执行失败才会执行后面的命令
                //获取cmd窗口的输出信息
                string output = p.StandardOutput.ReadToEnd();
                p.WaitForExit();//等待程序执行完退出进程
                p.Close();

最重要的一点,程序猿不应该忘记的一点:日志!日志!日志!   

        日志这块我是用了log4net来记录下载失败的文件,内容如下:

xda66

     文章中所用到的源码我上传到网盘里面了 

    下载地址https://pan.baidu.com/s/10hGQx6GB1trfTy0yflnMqw 提取码: 1dui 

    本文中的代码只用于借鉴和学习交流使用,用作他途本人概不负责


标签: .net 视频下载

1

评论文明上网,理性发言0条评论