Go
[Go & Fiber] 동영상 스트리밍 구현
Readerr
2023. 7. 2. 23:51
320x100
Go & Fiber는 이미 설치되어 있다고 가정합니다.
아니라면, 아래 포스팅을 참고해주세요.
https://readerr.tistory.com/100
소스 저장소
https://github.com/WOOOOOOOONG/GO-Fiber-Streaming
GitHub - WOOOOOOOONG/GO-Fiber-Streaming: 동영상 스트리밍 코드입니다.
동영상 스트리밍 코드입니다. Contribute to WOOOOOOOONG/GO-Fiber-Streaming development by creating an account on GitHub.
github.com
결과
패키지 다운로드
go get -u github.com/gorilla/websocket
go get -u github.com/gorilla/mux
파일 구조
public
- index.html
server.go
백엔드 코드 (server.go)
참고로, 반드시 48번째줄 코드에서 경로와 비디오 파일을 별도로 넣어주셔야 합니다.
package main
import (
"log"
"net/http"
"os"
"path/filepath"
"time"
"github.com/gorilla/mux"
"github.com/gorilla/websocket"
)
var upgrader = websocket.Upgrader{
CheckOrigin: func(r *http.Request) bool {
return true
},
}
func main() {
r := mux.NewRouter()
// 사이트 홈을 public/index.html로 지정
r.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, "public/index.html")
})
r.HandleFunc("/ws", handleWebSocket)
r.HandleFunc("/video/{filename}", handleVideoStream)
log.Println("Server started on http://localhost:3000")
log.Fatal(http.ListenAndServe(":3000", r))
}
func handleWebSocket(w http.ResponseWriter, r *http.Request) {
conn, err := upgrader.Upgrade(w, r, nil)
if err != nil {
log.Println("WebSocket upgrade failed:", err)
return
}
defer conn.Close()
// 클라이언트에서 WebSocket 연결이 성공적으로 열리면 해당 로직이 실행됩니다.
log.Println("WebSocket connection established")
// 동영상 파일을 열어서 전송할 준비를 합니다.
/ // 해당 경로에 반드시 파일을 넣어주세요.
file, err := os.Open("path/to/video.mp4")
if err != nil {
log.Println("Failed to open video file:", err)
return
}
defer file.Close()
bufferSize := 1024 * 4 // 4KB의 버퍼 크기로 설정합니다.
buffer := make([]byte, bufferSize)
// 파일을 읽어서 WebSocket을 통해 클라이언트로 전송합니다.
for {
// 버퍼에 데이터를 읽어옵니다.
n, err := file.Read(buffer)
if err != nil {
log.Println("Failed to read video file:", err)
break
}
// 버퍼의 내용을 클라이언트로 전송합니다.
if err := conn.WriteMessage(websocket.BinaryMessage, buffer[:n]); err != nil {
log.Println("Failed to send video data over WebSocket:", err)
break
}
// 전송 속도 제어를 위해 10ms 대기합니다.
time.Sleep(10 * time.Millisecond)
}
log.Println("Video streaming completed")
}
func handleVideoStream(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
filename := vars["filename"]
filePath := filepath.Join(".", "videos", filename)
file, err := os.Open(filePath)
if err != nil {
log.Println("Failed to open video file:", err)
http.NotFound(w, r)
return
}
defer file.Close()
w.Header().Set("Content-Type", "video/mp4")
http.ServeContent(w, r, "", time.Now(), file)
}
클라이언트 코드 (public/index.html)
<!DOCTYPE html>
<html>
<head>
<title>Video Streaming</title>
<style>
#video-container {
width: 640px;
height: 480px;
margin: 0 auto;
}
</style>
</head>
<body>
<div id="video-container">
<video id="video-player" controls></video>
</div>
<script>
const videoPlayer = document.getElementById('video-player');
// WebSocket 연결
const ws = new WebSocket('ws://localhost:3000/ws');
// WebSocket 이벤트 리스너
ws.onopen = function(event) {
console.log('WebSocket connection opened');
};
ws.onmessage = function(event) {
// 서버로부터 동영상 데이터 수신 시 처리
const data = event.data;
const videoBlob = new Blob([data], { type: 'video/mp4' });
const videoUrl = URL.createObjectURL(videoBlob);
videoPlayer.src = videoUrl;
};
ws.onclose = function(event) {
console.log('WebSocket connection closed');
};
</script>
</body>
</html>
실행
go run server.go
이후 localhost:3000에서 확인
그럼, 오늘 하루도 좋은 하루 되세요!
320x100