如何通过 youtube-dl 接收的数据在客户端创建视频文件?

Posted

技术标签:

【中文标题】如何通过 youtube-dl 接收的数据在客户端创建视频文件?【英文标题】:How to create video file in client from data receiving by youtube-dl? 【发布时间】:2020-11-06 01:52:48 【问题描述】:

我正在通过在后端使用 youtube-dl 和 php 构建一个小的 youtube 下载器。 当用户提交 youtube 视频 url 时,php 正在执行 youtube-dl.exe 并将视频数据直接传递给客户端,因为我避免它在后端下载视频,而不是再次将其下载到前端。

这里是我将流直接传递给客户端的 php 代码:

 header("Content-Disposition: attachment; filename=\"...\"" );
 header("Content-Type: application/octet-stream");
 passthru("$pathToYouTubedlExe -o - $youtube_video_url");

到达客户端的视频数据看起来像这样,它是一个字符串:

ftypmp42 isommp42 �moov lmvhd � �B� �BX �@ iods O��)� �trak \tkhd �B 2 @ � h $edts elst 2 �mdia mdhd � �B $ � � � � � y � � 3 � � Y � � � 0 > ^ � � [ X � � � 3 ! % � y 6 3 $stco �z� �p kx �k �trak \tkhd ���B� �B �@ =mdia mdhd � �B �B �D �U� Lhdlr soun IsoMedia 文件由 Google 制作,5 -11-2011 �minf smhd $dinf dref url �stbl istsd Ymp4a �D 5esds ' @ Q ��� stts f 4stsc �stsz f + % # & # ! " ! 8 ! & 4 - # ! = 3 6 Q O � � " " % #" ! % 5 Q F F F ? 8 6 $stco b� �T6 �1 �B �mdat +e����ϔP �Ў�j�� �Dٸ����a &X...m... ��=~��xwU�1��Ć́\��H���k�Ы ���.�(�ثg�b��������?�����>��A�=�)freeIsoMedia 文件由 Google 生成

这是到达客户端的数据。 我的问题是如何为该特定视频创建视频文件,例如 mp4 或 webm 或任何其他可用扩展?

我用 blob 尝试过:

 let response = await axios.get("http://localhost/youtube-dl/index.php",
      params: 
        download_video:JSON.stringify(this.videoInfo)
      
    , responseType:"application/octet-stream" );

 const props = type: "octet/stream";
 const props2 = type: "video/mp4"; / <<---- not working too
 let file;
 try 
    file = new File([response.data],"test.mp4", props);
  catch (e) 
    file = new Blob([response.data], props);
 
 var fileURL = window.URL.createObjectURL(file);
 let fileLink = document.createElement("a");
 fileLink.href = fileURL;
 fileLink.setAttribute("download","test.mp4")
 document.body.appendChild(fileLink);
 fileLink.click();

我尝试用该视频数据创建一个 json 对象,希望可能有一个带有 JSON.parse(response.data) 的对象 json 结构,但它不起作用。

【问题讨论】:

【参考方案1】:

响应数据应该已经是二进制数据,尽管您似乎正在尝试将字节值显示为文本。您可以尝试下面的代码,或者使用 FileReader API 作为另一种保存方法。

试试:

var fileLink = document.createElement('a');
fileLink.download = 'test.mp4'; 

let blob = new Blob([response.data], type: 'octet/stream');

fileLink.href = URL.createObjectURL(blob);

fileLink.click();

URL.revokeObjectURL(fileLink.href);

编辑

查看this thread 是否有助于 Axios 方面。 我对 Axios 不熟悉,但 online example 提供了一个线索,它应该如下所示:

var vid_url = 'https://www.yoursite.com/yourPHP_Passthru_Script.php';

axios.get(vid_url, 
    responseType: 'arraybuffer'
)
.then(function (response) 
    res.type('application/octet-stream');
    res.end( response.data, 'binary' );
);

【讨论】:

感谢您的回答,但您的示例也不起作用。你是对的 response.data 作为字符串到达​​。我怎样才能使它成为二进制文件。我在 axios 请求中将响应类型定义为八位字节/流,但它仍然作为字符串到达​​。我尝试使用客户端中的一种方法使其二进制化,但如果视频有点大,它会阻塞浏览器。你有任何其他的想法如何使它像二进制? 你的 PHP header 没问题。我对 Axios 不熟悉,但 some research 说试试:responseType: 'arraybuffer'。如果仍然失败,那么首先将props 更改为type: "application/octet-stream"; ...另一个最后的选择是忘记Axios,只使用标准XHR 请求从PHP 获取字节。

以上是关于如何通过 youtube-dl 接收的数据在客户端创建视频文件?的主要内容,如果未能解决你的问题,请参考以下文章

使用youtube-dl和yt-dlp下载视频!

youtube-dl:通过忽略 archive.txt 中指定的视频,将 youtube 视频 info.json 下载到播放列表中

Youtube-dl - 提取元数据/json 信息到文本文件

通过 php 使用 youtube-dl 时出现 Python ImportError

如何使用 ffplay 和 youtube-dl 在终端中播放 youtube 歌曲

如何在将 youtube-dl 用作 python 模块时列出视频分辨率?