1

iam building a little youtube downloader by using youtube-dl and php in the backend. When user submits a youtube video url, php is executing youtube-dl.exe and passing the video data directly to the client because i avoided it to download the video in the backend and than again to download it to the frontend.

Here the php code where iam passing the stream directly to the client:

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

The video data which arrives at the client looks like that and its a string:

ftypmp42 isommp42 �moov lmvhd � �B� �B X � @ iods O��)� �trak \tkhd � �B 2 @ � h $edts elst 2 �mdia mdhd � �B < �U� -hdlr vide VideoHandler �minf vmhd $dinf dref url dstbl �stsd �avc1 �h H H �� .avcCB��� gB����� ��b� h�<� btrt + ]X *� stts C stss = @stsc stsz C + 7 / � � � 2 : � � � N � t � J � � � F � 0 # ? Q �
$ � � � � � � 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 File Produced by 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� ����~�J�R��jf�NMB�T�&h�Yd!���䲭�Ԙ +c�Q�HOj�̑Rv��U�,���L��=~��xwU�1��Ć́\��H���k�Ы ���.�(�ثg�b��������?�����>��A�=� )freeIsoMedia File Produced By Google

Thats the data which arrives at the client. My question is how can i create a video file, like mp4 or webm or any other available extension for that particular video?

i tried it with a 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();

I tried it to create a json object with that video data in hope that maybe there is an object json structure with JSON.parse(response.data) but it does not work.

DealZg
  • 136
  • 1
  • 3
  • 14

1 Answers1

0

The response data should already be as binary data, although it seems you are trying to display the byte values as text. You can try the code below or else use the FileReader API as an alternative method for saving.

Try:

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);

Edit:

See if this thread helps with Axios side. I'm not familiar with Axios but an online example gives a clue that it should look something like below:

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' );
});
VC.One
  • 14,790
  • 4
  • 25
  • 57
  • Thank you for your answer but your example doesnt work either. You are right the response.data arrives as a string. How can i make it as a binary. I defined the response type as octet/stream in axios request but it still arrives as a string. I tried to make it binary with a method in the client which makes it binary but if the video is a bit bigger it blocks the browser. You have any other ideo how to make it like binary? – DealZg Jul 20 '20 at 20:41
  • Your PHP `header` is fine. I'm not familiar with Axios but [**some research**](https://stackoverflow.com/a/44021663/2057709) says to try: `responseType: 'arraybuffer'`. If that still fails then also change first `props` to become as `{type: "application/octet-stream"};` ... Another final option is to forget Axios and just use standard XHR request to get bytes from PHP. – VC.One Jul 21 '20 at 14:41