일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 | 31 |
- prisma timezone
- Spring
- Date
- node stream
- node js
- 스트림
- 노드 스트림
- prisma 시간
- 자바스크립트 시간 조절
- prisma
- 일시정지 모드
- node
- node 스트림
- javascript
- SESSION
- 동영상 스트리밍
- tomcat
- 흐름 모드
- node.js
- Stream
- 구현
- nodejs
- servlet
- 번역
- 자바스크립트 시간
- javascsript
- java
- 스트리밍
- jsp
- Today
- Total
벤권의 개발자 이야기
Node.js 비디오 스트리밍 서버 구현하기 본문
들어가기 전에
이전에 작성했던 포스팅에서 스트림을 다뤘는데 (아직 다 못썼다...시간 날 때 써야하는데 너무 길어서 읽어만 두었다.) 현재 진행하고 있는 개인 취미 프로젝트에서 비디오 스트리밍을 해야할 일이 생겼다. 말 그대로 비디오 스트리밍은 스트림을 이용해야한다. 물론 버퍼형식으로 비디오 전체를 다운로드해서 재생하는 방법도 있지만 매우 비효율적인건 안봐도 비디오이다.
이번 포스팅에서는 express를 이용한 웹 서버에서 Node JS 비디오 스트리밍 서버를 만들어보려고한다.
우선 비디오 스트리밍을 하기 위한 페이지가 필요하다.
코드는 아래와 같다.
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"/>
<title>Video Player</title>
</head>
<body>
<h1>Video Player</h1>
<video id="videoPlayer" width="650" controls muted="muted" autoplay>
<source src="/video" type="video/mp4" />
</video>
</body>
</html>
위 코드에서 video태그를 이용하여 source태그에 있는 src속성값으로 get 요청을 보내게 된다.
실제로 브라우저 상에서 해당 요청의 헤더값을 살펴보면
GET방식으로 헤더에 Range라는 속성이 있다. 여기서 Range는 클라이언트에서 서버에게 Range이후 부터 보내주면 된다라고 알려주는 헤더이다.
Range속성은 개발자가 부여하는 것이 아닌 video 태그를 이용하면 자동으로 헤더에 붙어서 전송이 된다.
따라서 서버에서는 전송할 비디오를 요청받으면 요청 헤더에 붙은 Range 값으로부터 스트림으로 한번에 보낼 chunk사이즈만큼 잘라내서 다시 전송해주면된다.
그럼 이제 노드 서버 파일을 보도록 하자.
const express = require("express");
const app = express();
const fs = require("fs");
// 비디오 용량 미리 가져와 놓기
const videoPath = "myvideo.mp4";
const videoSize = fs.statSync("myvideo.mp4").size;
app.get("/", function (req, res) {
res.sendFile(__dirname + "/index.html");
});
app.get("/video", function (req, res) {
// Ensure there is a range given for the video
const range = req.headers.range;
console.log(range)
if (!range) {
res.status(400).send("Requires Range header");
}
const CHUNK_SIZE = 10 ** 6; // 1MB
const start = Number(range.replace(/\D/g, ""));
const end = Math.min(start + CHUNK_SIZE, videoSize - 1);
// Create headers
const contentLength = end - start + 1;
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);
// create video read stream for this particular chunk
const videoStream = fs.createReadStream(videoPath, { start, end });
// Stream the video chunk to the client
videoStream.pipe(res);
});
app.listen(8000, function () {
console.log("Listening on port 8000!");
});
express에서 res와 req는 기본적으로 스트림이다. (express res,req는 http 모듈의 ServerResponse,ClientRequest 기반이다)
그래서 그냥 res를 writable stream으로 생각하고 서버에서 스트리밍할 비디오를 클라이언트에서 요청한 range부터 chunk size만큼 잘라서 파이프로 연결시켜주면된다.
물론 이벤트 방식으로 데이터를 보내줘도 된다.
(참고 : https://javafa.gitbooks.io/nodejs_server_basic/content/chapter11.html)
이런식으로 하면 클라이언트는 오랜시간을 기다리지 않아도 대용량의 비디오를 실시간으로 재생할 수 있게 된다.
마치며
나는 경력없는 백수로 실무에서 사실 Node js가 어떻게 쓰이는지 모른다. 하지만 개인적으로 노드를 공부해나가면서 느낀점은 스트림은 정말 중요한 개념인 것 같다. 물론 노드가 아니더라도 모든 개발자에게 중요한 개념인 것 같다. 하루 빨리 기나긴 노드 스트림 내 맘대로 번역 및 정리를 마무리 해야겠다.
참고
https://github.com/Abdisalan/blog-code-examples/tree/master/http-video-stream
'- > node' 카테고리의 다른 글
Node.js Streams에 대하여 4부 (스트림 구현) (2) | 2022.04.07 |
---|---|
Node.js Streams에 대하여 3부 (2) | 2022.02.25 |
Node.js Streams에 대하여 2부 (4) | 2022.02.24 |
Node.js Streams에 대하여 1부 (3) | 2022.02.24 |
child_process모듈의 execFile, exec, spawn, fork 이해하기 (1) | 2022.02.22 |