본문으로 바로가기

HTML5 VIDEO 스트리밍(STREAMING) 서버 프로그래밍 - JAVA

category JAVA 2018. 3. 7. 10:33
반응형



HTML5 VIDEO 스트리밍(STREAMING) 서버 프로그래밍 - JAVA



오늘은 HTML5 태그 중 VIDEO 기능에 대해 소개 하려고 합니다.
VIDEO 태그는 웹에서 동영상을 플레이 하기 위한 기능입니다. 예전에는 active X 방식이나 별도의 플러그인 형태로 동영상을 재생 했었습니다.


하지만, 동영상을 재생하기 위해 스트리밍을 할 필요가 있습니다. 꼭 스트리밍 방식이 아니여도 상관은 없을테지만 용량이 큰 동영상의 경우에는 반드시 스트리밍 방식이 필요합니다. 아래는 스트리밍 처리를 위한 서버사이드(java)측 내용을 공유 하려고 합니다.


아래 내용에서 주요 관심 포인트는 다음과 같습니다.
1. HTTP RESPONSE 응답 코드

2. HTTP REQUEST 헤더의 RANGE


우선 HTML의 VIDEO 태그 사용 방법은 아실거라 생각 하고 패스 합니다.


- StreamingResponse.java


import java.io.File;

import java.io.IOException;


import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;


public class StreamingResponse {


public static final int DEFAULT_BUFFER_SIZE = 204800;


private static final String CONTENT_TYPE = "video/mp4";


private static final long DEFAULT_EXPIRE_TIME = 604800000L;


public Range write(File file, HttpServletRequest request, HttpServletResponse response) throws IOException {

Range range = null;

String rangeStr = request.getHeader("range");

if (rangeStr != null) {

if (rangeStr.endsWith("-")) {

rangeStr = rangeStr + (file.length() - 1);

}

int idxm = rangeStr.trim().indexOf("-");

range = new Range(Long.parseLong(rangeStr.substring(6, idxm)), Long.parseLong(rangeStr.substring(idxm + 1)), file.length());

if (range.start > 0) {

range.isPart = true;

}

} else {

range = new Range(0, file.length() - 1, file.length());

}

range.partSize = range.end - range.start + 1;

if (range.end == 0) {

range.end = range.start + DEFAULT_BUFFER_SIZE - 1;

}

if (range.end > file.length() - 1) {

range.end = file.length() - 1;

}


String eTag = file.getName() + "_" + range.length + "_" + file.lastModified();


response.reset();

response.setStatus(range.isPart ? HttpServletResponse.SC_PARTIAL_CONTENT : HttpServletResponse.SC_OK);

response.setContentType(CONTENT_TYPE);

response.setHeader("Content-Range", "bytes " + range.start + "-" + range.end + "/" + range.total);

response.setHeader("Accept-Ranges", "bytes");

response.setHeader("Content-Length", "" + range.partSize);


response.setBufferSize(DEFAULT_BUFFER_SIZE);

response.setHeader("Content-Disposition", "inline;filename=\"" + file.getName() + "\"");

response.setHeader("ETag", eTag);

response.setDateHeader("Last-Modified", file.lastModified());

response.setDateHeader("Expires", System.currentTimeMillis() + DEFAULT_EXPIRE_TIME);

return range;

}

}



위 소스코드에서 중요한 포인트는 HTTP REQUEST 헤더에서 RANGE 속성을 찾아 요청된 START, END 값을 찾습니다.

RANGE 속성의 값이 있다면 PARTIAL 콘텐츠 요청이라고 판단 하여 동영상의 일부를 보내야 합니다.




- StreamingUtil.java


import java.io.File;

import java.io.IOException;

import java.io.OutputStream;

import java.io.RandomAccessFile;


import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;


import org.apache.commons.io.IOUtils;


public class StreamingUtil {


public void streaming(File file, HttpServletRequest request, HttpServletResponse response, OutputStream out) throws IOException {

StreamingResponse streamingResponse = new StreamingResponse();

Range range = streamingResponse.write(file, request, response);

copyStreaming(file, out, range);

}


private void copyStreaming(File file, OutputStream output, Range range) {

RandomAccessFile randomFile = null;

try {

long partSize = range.partSize;

randomFile = new RandomAccessFile(file, "r");

randomFile.seek(range.start);

byte[] buf = new byte[StreamingResponse.DEFAULT_BUFFER_SIZE];

do {

int block = partSize > StreamingResponse.DEFAULT_BUFFER_SIZE ? StreamingResponse.DEFAULT_BUFFER_SIZE : (int) partSize;

int len = randomFile.read(buf, 0, block);

output.write(buf, 0, len);

output.flush();

partSize -= block;

} while (partSize > 0);

} catch (Exception e) {

//log.info("User canceled streaming request");

} finally {

IOUtils.closeQuietly(randomFile);

}

}

}


찾아낸 RANGE 속성 만큼 부분 영상 데이터를 보내게 됩니다.

브라우저에서 개발자 도구(F12) 네트워크를 통해 확인을 하게 되면 영상이 실제로 부분 데이터가 전송 되는 것을 확인 할 수 있습니다.

또한 영상 스킵도 가능하고, 빠르게 재생 됨을 확인 할 수 있습니다.


기타 궁금한 사항은 댓글을 달아주세요.






반응형