I want to send a YouTube video which is converted in my API node js with ytdl-core to my client for downloading it. It works if I use a navigator for ask to my API but I can't download when I use my client.
The two way I tried:
video.pipe(reponse);
I receive something like that:
§W��JXIn�!�↓#�▲If�Z2��Y�F∟��6�
♠♂4�o�C4�-KeoX�@↔;#%◄Z↔¶������cl�N♦�5Z8��Ζ��↓��fƦ�P¤�{P�◄�ټ�֩��S��ŗ�Z�↑����.�☻j��G�▬�\L�2�ލ▬�|�T�w<�¶☺�☼!zTMʌ��� L#
n=♠V♣nMT�֑zr☺��o�l���↕�iʮ��♫�3���W�lK���x}��7↨4q
�zV��5kB��a�m��∟y◄��Xx5�l�OYkFX?�9s��g�♫���0St��#$4#4� �J���♂U◄Ĺ;Á�♀Qž?
R߈/��˽}KeoX�@↔�!b�k�u�RhĀR▼$��b�0�ɉIi %�Es�&�u���dvK♥g→E☻ .��ݒ����}�[∟��♣;☼=f� ....
or
reponse.status(200).send(video);
I receive that:
{
_readableState: {
objectMode: false,
highWaterMark: 524288,
buffer: { head: null, tail: null, length: 0 },
length: 0,
pipes: [],
flowing: null,
ended: false,
endEmitted: false,
reading: false,
constructed: true,
sync: false,
needReadable: false,
emittedReadable: false,
readableListening: false,
resumeScheduled: false,
errorEmitted: false,
emitClose: true,
autoDestroy: true,
destroyed: false,
errored: null,
closed: false,
closeEmitted: false,
defaultEncoding: 'utf8',
awaitDrainWriters: null,
multiAwaitDrain: false,
readingMore: false,
dataEmitted: false,
decoder: null,
encoding: null
},
_events: {},
_eventsCount: 1,
_writableState: {
objectMode: false,
highWaterMark: 524288,
finalCalled: false,
needDrain: false,
ending: false,
ended: false,
finished: false,
destroyed: false,
decodeStrings: true,
defaultEncoding: 'utf8',
length: 0,
writing: false,
corked: 0,
sync: true,
bufferProcessing: false,
writecb: null,
writelen: 0,
afterWriteTickInfo: null,
buffered: [],
bufferedIndex: 0,
allBuffers: true,
allNoop: true,
pendingcb: 0,
constructed: true,
prefinished: false,
errorEmitted: false,
emitClose: true,
autoDestroy: true,
errored: null,
closed: false,
closeEmitted: false
},
allowHalfOpen: true
}
[nodemon] restarting due to changes...
[nodemon] starting `node index.js`
server started ! : port 5000
{
_readableState: {
objectMode: false,
highWaterMark: 524288,
buffer: { head: null, tail: null, length: 0 },
length: 0,
pipes: [],
flowing: null,
ended: false,
endEmitted: false,
reading: false,
constructed: true,
sync: false,
needReadable: false,
emittedReadable: false,
readableListening: false,
resumeScheduled: false,
errorEmitted: false,
emitClose: true,
autoDestroy: true,
destroyed: false,
errored: null,
closed: false,
closeEmitted: false,
defaultEncoding: 'utf8',
awaitDrainWriters: null,
multiAwaitDrain: false,
readingMore: false,
dataEmitted: false,
decoder: null,
encoding: null
},
_events: {},
_eventsCount: 1,
_writableState: {
objectMode: false,
highWaterMark: 524288,
finalCalled: false,
needDrain: false,
ending: false,
ended: false,
finished: false,
destroyed: false,
decodeStrings: true,
defaultEncoding: 'utf8',
length: 0,
writing: false,
corked: 0,
sync: true,
bufferProcessing: false,
writecb: null,
writelen: 0,
afterWriteTickInfo: null,
buffered: [],
bufferedIndex: 0,
allBuffers: true,
allNoop: true,
pendingcb: 0,
constructed: true,
prefinished: false,
errorEmitted: false,
emitClose: true,
autoDestroy: true,
errored: null,
closed: false,
closeEmitted: false
},
allowHalfOpen: true
}
I don't know how to down load it because pipe don't work when I receive the 2 answers.
CodePudding user response:
you can use gstream nodejs/npm integration
sudo apt-get install gstreamer-tools
npm install gstreamer
var gstreamer = require("../");
gstreamer.start({
url: "rtsp://wowzaec2demo.streamlock.net/vod/mp4:BigBuckBunny_115k.mov?random=" Math.random(),
//url: "rtsp://192.168.1.92:554//1",
port: 80,
quiet: false
});
CodePudding user response:
then, try the following:
$ npm init
$ sudo apt install youtube-dl
$ sudo apt install ffmpeg
$ npm install shelljs;
$ npm install -g shelljs;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Video Streaming With Node</title>
<style>
body {
margin: 5% auto;
max-width: 100%;
background-color: rgb(14, 14, 14);
padding-top: 10%;
padding-left: 35%;
}
</style>
</head>
<body>
<video id="videoPlayer" width="50%" controls muted="muted" autoplay>
<source src="/video" type="video/mp4" />
</video>
</body>
</html>
const shx = require('shelljs');
shx.exec("youtube-dl rtsp://wowzaec2demo.streamlock.net/vod/mp4:BigBuckBunny_115k.mov?random=" Math.random());
// *********************************************** //
const express = require("express");
const app = express();
const fs = require("fs");
app.get("/", function (req, res) {
res.sendFile(__dirname "/index.html");
});
// more code will go in here just befor the listening function
app.listen(8000, function () {
console.log("Listening on port 8000!");
});
// *********************************************** //
app.get("/video", function (req, res) {
const range = req.headers.range;
if (!range) {
res.status(400).send("Requires Range header");
}
});
// *********************************************** //
const videoPath = "Chris-Do.mp4";
const videoSize = fs.statSync("Chris-Do.mp4").size;
// *********************************************** //
const express = require("express");
const app = express();
const fs = require("fs");
app.get("/", function (req, res) {
res.sendFile(__dirname "/index.html");
});
app.get("/video", function (req, res) {
const range = req.headers.range;
if (!range) {
res.status(400).send("Requires Range header");
}
const videoPath = "Chris-Do.mp4";
const videoSize = fs.statSync("Chris-Do.mp4").size;
});
app.listen(8000, function () {
console.log("Listening on port 8000!");
});
// *********************************************** //
const CHUNK_SIZE = 10 ** 6; // 1MB
const start = Number(range.replace(/\D/g, ""));
// *********************************************** //
const start = Number(range.replace(/\D/g, ""));
// *********************************************** //
const end = Math.min(start CHUNK_SIZE, videoSize - 1);
// *********************************************** //
const headers = {
"Content-Range": `bytes ${start}-${end}/${videoSize}`,
... // this ... just indicates that there is more code here.
// it is not part of code.
}
// *********************************************** //
const headers = {
"Content-Range": `bytes ${start}-${end}/${videoSize}`,
"Accept-Ranges": "bytes",
"Content-Length": contentLength,
"Content-Type": "video/mp4",
};
// *********************************************** //
// HTTP Status 206 for Partial Content
res.writeHead(206, headers);
// *********************************************** //
const videoStream = fs.createReadStream(videoPath, { start, end });
// *********************************************** //
videoStream.pipe(res);
// *********************************************** //
const end = Math.min(start CHUNK_SIZE, videoSize - 1);
const contentLength = end - start 1;
const headers = {
"Content-Range": `bytes ${start}-${end}/${videoSize}`,
"Accept-Ranges": "bytes",
"Content-Length": contentLength,
"Content-Type": "video/mp4",
};
res.writeHead(206, headers);
const videoStream = fs.createReadStream(videoPath, { start, end });
videoStream.pipe(res);
});
app.listen(8000, function () {
console.log("Listening on port 8000!");
});
const end = Math.min(start CHUNK_SIZE, videoSize - 1);
const contentLength = end - start 1;
const headers = {
"Content-Range": `bytes ${start}-${end}/${videoSize}`,
"Accept-Ranges": "bytes",
"Content-Length": contentLength,
"Content-Type": "video/mp4",
};
res.writeHead(206, headers);
const videoStream = fs.createReadStream(videoPath, { start, end });
videoStream.pipe(res);
});
app.listen(8000, function () {
console.log("Listening on port 8000!");
});
// *********************************************** //
"scripts": {
"start": "nodemon index.js" //this is the main line you need to add
},
//note that the index.js is just the name of my file. yours might be named differently
if you want the full reply, here you have it: