一、概要

1、Youtube-dl工具

强大的视频下载命令行工具Youtube-dl项目由Ricardo Garcia创建于2008年,源代码由Python编写,托管在GitHub上,
最初仅支持YouTube,但随着项目的发展,也开始支持其他视频网站,优势在于使用简单、功能齐全、体积小巧,
但唯一遗憾的是国内使用需要开启代理。 可以从YouTube、Dailymotion、Google Video、Photobucket、Facebook、Yahoo、Metacafe、Depositfiles、Bilibili 和类似网站下载视频。
目前已知 youtube-dl 所支持的国内、外音、视频平台共有 1226 个之多,详情请参考:
http://ytdl-org.github.io/youtube-dl/supportedsites.html 
它不受平台限制,可以在任何 GNU/Linux、Windows 或 macOS 系统上运行。
  下载地址:

https://github.com/ytdl-org/youtube-dl

该脚本源代码基于Python 编写,需要安装 Python 3.2以上版本,Python 下安装命令:

#直接安装 youtube-dlpip install youtube-dl#更新安装 youtube-dlpip install --upgrade youtube-dl

2、FFmpeg组件

​ FFmpeg是处理多媒体内容(例如音频、视频、字幕和相关元数据)的库和工具的集合。FFmpeg是处理多媒体内容(例如音频、视频、字幕和相关元数据)的库和工具的集合。从组件下载地址下载完成后,解压到想要的位置即可。
下载地址:(我下载的是gpl-shared版)
https://github.com/BtbN/FFmpeg-Builds/releases
​ 在这里使用FFmpeg的原因是:Youtube-dl下载的内容可能是音视频分开下载的(某些分辨率或者某些站点),用视频剪辑软件合并又要浪费一定的时间,而安装FFmpeg之后,则可以自动合并(merge)。
​ FFmpeg分为3个版本:Static,Shared,Dev。前两个版本可以直接在命令行中使用,他们的区别在于:

Static里面只有3个应用程序:ffmpeg.exe,ffplay.exe,ffprobe.exe,每个exe的体积都很大,相关的Dll已经被编译到exe里面去了。
Shared里面除了3个应用程序:ffmpeg.exe,ffplay.exe,ffprobe.exe之外,还有一些Dll,比如说avcodec-54.dll之类的。Shared里面的exe体积很小,他们在运行的时候,到相应的Dll中调用功能。
Dev版本是用于开发的,里面包含了include(头文件xxx.h)和lib(库文件xxx.lib),这个版本不包含exe文件。
​ 最后,确保已经在PATH中已经配置环境,我的配置如下:
​ 按Win+R或直接在任务栏搜索框,输入“cmd”,再输入以下命令,检测是否安装成功,

ffmpeg -version

二、Delphi调用Cmd命令行并能过管道取得返回结果

使用CreateProcess创建cmd进程。

 zeromemory(@sa,sizeof(sa));sa.nLength := Sizeof(sa);设置允许继承,否则在NT和2000下无法取得输出结果sa.bInheritHandle := True;sa.lpSecurityDescriptor := nil;hReadPipe:=0;hWritePipe:=0;
try//创建管道ret := CreatePipe(hReadPipe, hWritePipe, @sa, 0);if not ret thenbeginuLog.Log('CreatePipe false.');exit;end;//FillChar(StartupInfo, SizeOf(StartupInfo), 0);zeromemory(@StartupInfo, SizeOf(StartupInfo));StartupInfo.cb := sizeof(StartupInfo);GetStartupInfo(StartupInfo);//使用指定的句柄作为标准输入输出的文件句柄,使用指定的显示方式StartupInfo.dwFlags:=STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;StartupInfo.wShowWindow:=SW_HIDE; //SW_HIDEStartupInfo.hStdOutput:=hWritePipe;StartupInfo.hStdError:=hWritePipe;zeromemory(@ProcessInfo, SizeOf(ProcessInfo));ret:=CreateProcess(nil,pchar(cmdline), @sa, @sa, true, 0, nil, pchar(uConfig.workdir), StartupInfo, ProcessInfo);//从管道读取cmd返回的信息
function TTubeDown.getPipeInfo2(hReadPipe:THandle):string;
var//buf:array[0..1023] of ansichar;buf:array[0..1023] of byte;lngBytesread:cardinal;ret:BOOL;dwRead,dwAvail:DWORD;
beginresult:='';ret:=true;while ret dobeginif(not PeekNamedPipe(hReadPipe, nil, 0, @dwRead, @dwAvail, nil))then break;if(dwAvail<=0)then break;FillChar(buf,Sizeof(buf),#0);ret := ReadFile(hReadPipe, buf, 1024, lngBytesread, nil);if(lngBytesread<=0)then break;//result:=result+string(buf);result:=getStringFrombuf(buf,lngBytesRead);end;
end;

三、完整代码:

unit uTubeDown;interface
useswindows,classes,strutils,sysutils,uLog,uConfig,uAuth;
constwm_user=$0400;wm_downfile=wm_user+100+1;//cmd命令类别CMD_DOWN=1;                  //下载CMD_FIND=2;                    //查询CMD_FIND_DOWN=3;       //查询下载CMD_UPGRADE=4;           //升级 //cmd参数PARAM_FIND='-F';              //查询PARAM_FIND_DOWN='-f';    //查询下载PARAM_FIND_BEST='-f best';     //以最高分辨率下载
typeTTubeDown=class(TThread)privateFId:cardinal;Furl:string;                        //视频地址Ffilename:string;          //保存的文件名FsaveDir:string;           //保存目录 Fmsg:string;               //消息Fcmd:integer;            //cmd命令类别Fparam:string;              //视频地址class var Fform: HWND;       //视频地址procedure SetId(id:cardinal);procedure SetCmd(cmd:integer);procedure SetParam(param:string);procedure SetSaveDir(dir:string);class procedure SetForm(const hForm: HWND); static;function getPipeInfo(hReadPipe:THandle):string;function getPipeInfo2(hReadPipe:THandle):string;function getStringFromBuf(buf:array of byte;length:integer):string;protectedprocedure Execute; override;publicconstructor Create(id:cardinal;url:string);destructor Destroy;function WaitExe(): integer;property id:cardinal read FId write SetId;property url:string read Furl;property msg:string read Fmsg;property filename:string read Ffilename;property cmd:integer read Fcmd write SetCmd;property param:string read Fparam write SetParam;property savedir:string read FsaveDir write SetSaveDir;class property form: HWND read Fform write SetForm;end;implementation
constructor TTubeDown.Create(id:cardinal;url:string);
begin//inherited;//FreeOnTerminate := True;inherited Create(True);FId:=id;Furl:=url;//FComplete:=false;
end;
destructor TTubeDown.Destroy;
begininherited Destroy;
end;
procedure TTubeDown.Execute;
beginWaitExe();
end;//-----------------------------------------------------------------------------------
//****************************************************
//* 函数功能:执行程序至完成
//* 函数名称: WaitExe
技术支持:QQ:39848872;V:byc6352
//****************************************************
function TTubeDown.WaitExe(): integer;
varsa:TSecurityAttributes;hReadPipe,hWritePipe:THandle;ret:BOOL;info:string;StartupInfo: TStartupInfo;ProcessInfo: TProcessInformation;lngBytesread,i:DWORD;cmdline:string;downcount:integer;dwRead:DWORD;buf:array[0..1023] of byte;
beginResult:=0;if(Fcmd=CMD_UPGRADE)thenbegincmdline:=Furl;end else beginif(pos('bilibili',Furl)>0)thenbegincmdline:='bbdown -tv --work-dir '+Fsavedir+' '+Furl;end else if (pos('youtube.com/shorts',Furl)>0)thenbegin//cmdline:='you-get.exe --debug -o '+Fsavedir+' '+Furl;cmdline:='yt-dlp.exe -o '+Fsavedir+'/%(title)s.%(ext)s '+Fparam+' '+Furl;end else if (pos('twitter.com',Furl)>0)thenbegincmdline:='youtube-dl.exe -o '+Fsavedir+'/%(title)s.%(ext)s '+Fparam+' '+Furl;end else begin//yt-dlp.exe为youtube-dl的一个分支cmdline:='yt-dlp.exe -o '+Fsavedir+'/%(title)s.%(ext)s '+Fparam+' '+Furl;end;end;Log(cmdLine);zeromemory(@sa,sizeof(sa));sa.nLength := Sizeof(sa);sa.bInheritHandle := True;sa.lpSecurityDescriptor := nil;hReadPipe:=0;hWritePipe:=0;
tryret := CreatePipe(hReadPipe, hWritePipe, @sa, 0);  //创建管道if not ret thenbeginuLog.Log('CreatePipe false.');exit;end;//FillChar(StartupInfo, SizeOf(StartupInfo), 0);zeromemory(@StartupInfo, SizeOf(StartupInfo));StartupInfo.cb := sizeof(StartupInfo);GetStartupInfo(StartupInfo);StartupInfo.dwFlags:=STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;StartupInfo.wShowWindow:=SW_HIDE; //SW_HIDEStartupInfo.hStdOutput:=hWritePipe;StartupInfo.hStdError:=hWritePipe;zeromemory(@ProcessInfo, SizeOf(ProcessInfo));ret:=CreateProcess(nil,pchar(cmdline), @sa, @sa, true, 0, nil, pchar(uConfig.workdir), StartupInfo, ProcessInfo);if not ret thenbeginuLog.Log('CreateProcess false.');Exit;end;while true dobeginlngBytesread:=WaitForSingleObject(ProcessInfo.hProcess, 1000);//1秒钟输出一次信息;if(lngBytesRead=WAIT_FAILED)thenbeginuLog.Log('WaitForSingleObject false.');Exit;end;if(lngBytesRead= WAIT_OBJECT_0)then         //1秒获取信息一次beginif(Fcmd=CMD_FIND)theninfo:=getPipeInfo2(hReadPipe)         //取cmd输出信息elseinfo:=getPipeInfo(hReadPipe);Log(info);Fmsg:=info;SendMessage(Fform,wm_downfile,0,integer(self));  //信息发送至窗体info:='complete';Log(info);result:=1;Fmsg:=info;SendMessage(Fform,wm_downfile,0,integer(self));exit;end;if(lngBytesRead=WAIT_TIMEOUT)then             //cmd进程结束beginif(Fcmd=CMD_FIND)then continue;info:=getPipeInfo(hReadPipe);                    //取cmd输出信息Log(info);Fmsg:=info;SendMessage(Fform,wm_downfile,0,integer(self));end;end;result:=1;info:='complete over.';Log(info);Fmsg:=info;SendMessage(Fform,wm_downfile,0,integer(self));//------------------------------------------------------------
finallyif(hReadPipe<>0)then CloseHandle(hReadPipe);if(hWritePipe<>0)then CloseHandle(hWritePipe);if(ProcessInfo.hThread<>0)then  CloseHandle(ProcessInfo.hThread);if(ProcessInfo.hProcess<>0)then CloseHandle(ProcessInfo.hProcess);
end;
end;
//字节转换成字符串
function TTubeDown.getStringFromBuf(buf:array of byte;length:integer):string;
vartmp:array of byte;str:ansistring;
beginresult:='';if(length<=0)then exit;
trysetlength(tmp,length);copymemory(tmp,@buf[0],length);result:=Tencoding.UTF8.GetString(tmp);              //youtube等外网视频站点是utf8编码
exceptsetlength(str,length);copymemory(@str[1],@buf[0],length);result:=str;end;
end;
//非阻塞方式读取管道信息
function TTubeDown.getPipeInfo2(hReadPipe:THandle):string;
var//buf:array[0..1023] of ansichar;buf:array[0..1023] of byte;lngBytesread:cardinal;ret:BOOL;dwRead,dwAvail:DWORD;
beginresult:='';ret:=true;while ret dobeginif(not PeekNamedPipe(hReadPipe, nil, 0, @dwRead, @dwAvail, nil))then break;if(dwAvail<=0)then break;FillChar(buf,Sizeof(buf),#0);ret := ReadFile(hReadPipe, buf, 1024, lngBytesread, nil);if(lngBytesread<=0)then break;//result:=result+string(buf);result:=getStringFrombuf(buf,lngBytesRead);end;
end;
//阻塞方式读取管道信息
function TTubeDown.getPipeInfo(hReadPipe:THandle):string;
var//buf:array[0..1023] of ansichar;buf:array[0..1023] of byte;lngBytesread:cardinal;ret:BOOL;
beginresult:='';FillChar(buf,Sizeof(buf),#0);ret := ReadFile(hReadPipe, buf, 1024, lngBytesread, nil);if(ret=true)thenbegin//result:=buf;result:=getStringFrombuf(buf,lngBytesRead);end;
end;
{
procedure TTubeDown.start();
beginExecute;
end;
}
//------------------------------------------属性方法-------------------------------------procedure TTubeDown.SetId(Id:cardinal);beginFId:=Id;end;class procedure TTubeDown.SetForm(const hForm: HWND);beginFform:=hForm;end;procedure TTubeDown.SetCmd(cmd:integer);beginFcmd:=cmd;end;procedure TTubeDown.SetParam(param:string);beginFparam:=param;end;procedure TTubeDown.SetSaveDir(dir:string);beginFSaveDir:=dir;end;
end.

四、使用方法:

vartube:TTubeDown;
begintube:=TTubeDown.Create(i,url);tube.cmd:=CMD_DOWN;tube.param:='';tube.savedir:=uConfig.saveDir;tube.start();
end;

五、成品

delphi 调用youtube-dl命令,下载youtube视频,原理及源代码相关推荐

  1. GitHub 5W 星:一行命令下载全网视频的两个开源项目

    大家好,我是你们的 猫哥,那个不喜欢吃鱼.又不喜欢喵 的超级猫 ~ 前言 相信大多数人都有想下载某个网站上的视频的想法. 比如  B站.优酷.YouTube.腾讯视频等网站上的优质视频. 但是大多数视 ...

  2. GitHub 标星 32.7 k!一行命令下载全网视频,这个项目牛逼了!

    假期期间,小逛看到一个视频在朋友圈刷屏了,想必大家也都刷到了这个视频<后浪>.该视频是 bilibli 献给新一代的演讲,截至本文发布时,该视频已经有 1727.7w 播放,其它数据也是高 ...

  3. python播放视频 命令_一行命令下载全网视频,这个命令太牛逼了!

    原标题:一行命令下载全网视频,这个命令太牛逼了! 相信大家有遇到这样的情况,在网站上看到一些不错的视频,想要下载下来,但是没有找到网站的下载入口. 虽然像优酷.爱奇艺.腾讯视频都有自己的客户端,但下载 ...

  4. linux的yum命令无法使用在哪里下载_一行命令下载全网视频,这个命令太牛逼了!...

    相信大家有遇到这样的情况,在网站上看到一些不错的视频,想要下载下来,但是没有找到网站的下载入口. 虽然像优酷.爱奇艺.腾讯视频都有自己的客户端,但下载的视频都是它们专用格式,其它播放器无法播放. 今天 ...

  5. delphi 调用浏览器内核_深入理解浏览器原理

    导语:本文从市面主流的浏览器及相应的内核引擎开始,介绍了Chromium为代表的浏览器架构及Blink内核的功能架构.Chromium为多进程架构,用户从启动运行浏览器后,先后经过页面导航.渲染.资源 ...

  6. 利用Python you-get 下载网页视频

    平时可以使用python 下 you-get 命令 下载一些视频. 如果还没有python,请先安装 python 然后 ,如果是windows 下 ,先打开 cmd 命令行, 输入 pip inst ...

  7. python爬虫下载梨视频

    import requests import re import os from urllib.request import urlretrieve def download_vedio():'''下 ...

  8. Win10 Python yt-dlp下载youtube视频 | 安装使用详细教程

    目录 前言 0.科学上网 1.安装yt-dlp 2.安装FFmpeg 2.1 官网下载 2.2 环境变量配置 2.3 安装成果检查 3. 上手下载 3.1 基础格式 3.2 脚本地址查询 3.3 常用 ...

  9. 在电脑上下载 Youtube 的视频

    2019独角兽企业重金招聘Python工程师标准>>> 直接下载 youtube 的视频:http://en.savefrom.net/ 转载于:https://my.oschina ...

最新文章

  1. 交换排序之——冒泡排序(c/c++)
  2. Channel的几种状态
  3. Android序列化与反序列化
  4. tf.placeholder在测试时带来的坑
  5. nashPay项目遇到的问题
  6. C语言中float,double类型,在内存中的结构(存储方式).
  7. python获取系统内存占用信息的实例方法
  8. 【转】linux kernel 网络协议栈之GRO(Generic receive offload)
  9. [2020年]研究生数学建模竞赛题目分享
  10. 华为java安全编程规范考试答案
  11. SSM框架Web程序的流程(Spring SpringMVC Mybatis)
  12. 宝藏级UI组件库:FirstUI,微信小程序版+uniapp版更新至1.6.0,完美支持vue3
  13. 【noi.ac #1779】D
  14. 浙大翁凯老师Java课堂学习记录(第二周)
  15. Linux-虚拟机使用:真机与虚拟机ping通
  16. TrinityCore3.3.5环境搭建
  17. 微软浏览器edge对日期Date对象format(yyyy-mm-dd)/getDiff()方法不识别
  18. 宇视网络视频录像机升级步骤
  19. 【DBC】DBC文件格式详解
  20. 计算机sps材料,SPS网络通信-Phocos.PDF

热门文章

  1. 将.pkl文件转化为.csv
  2. 日常生活中要怎么记账
  3. 格式保留加密(FPE)及其使用Demo
  4. 牛客国庆集训派对Day2 H 卡牌游戏(花式蒙期望)
  5. 一款不错的打印控件,SailPrint打印组件简介。
  6. 一个拖延症的学习之旅
  7. [激光原理与应用-51]:《激光焊接质量实时监测系统研究》-2-激光焊接及其物理现象
  8. Java匿名内部类中this的小知识(待补充完整)
  9. 常见的压缩指令,认真看完
  10. 光纤通信系统简要复习