HTML5 비디오 태그를 통해 내 IPad로 비디오를 스트리밍하고 싶습니다. backend에서 tapestry5 (5.3.5)를 사용하고 싶습니다. 일반적으로 서버 측 프레임 워크는이 점에서 역할을하지 않아야하지만 어떻게 든 작동합니다.ipad 로의 비디오 스트리밍이 Tapestry5에서 작동하지 않습니다.
어쨌든 여기 누군가가 나를 도울 수 있습니다. 제 프로젝트는 매우 프로토 타입이며, 설명하는 내용은 관련 부분으로 단순화/축소된다는 점을 명심하십시오. 사람들이 "당신이 잘못된 일을하기를 원합니다"또는 문제와 관련이없는 보안/성능 닉픽으로 응답하지 않으면 매우 감사 할 것입니다.
그래서 여기 간다 :
설정
내가 애플 HTML5에서 가져온 비디오는 내가 형식이 문제가 아님을 알 수 있도록 전시 할 수 있습니다. 나는 단순히 "비디오"태그를 포함하는 간단한 tml 페이지 "재생"이 있습니다.
문제는 참조 된 비디오 파일을 열고 클라이언트에 스트리밍 비디오 컨트롤에서 요청을 처리하는 RequestFilter를 구현하여 시작했다. 기본은 "경로가 '파일'로 시작하고 파일 입력 스트림을 응답 출력 스트림으로 복사하는 경우"입니다. 이것은 Chrome에서 잘 작동하지만 Ipad에서는 작동하지 않습니다. 좋아, 나는 비록 내가 놓친 일부 헤더가 있어야한다. 그래서 나는 Apple Showcase를 다시보고 똑같은 헤더와 내용 유형을 포함했지만 기쁨은 없었다.
다음으로 나는 t5가 파일을 제공하도록하면 어떻게되는지 보도록하겠습니다. 웹 응용 프로그램 컨텍스트에 비디오를 복사하고 요청 필터를 비활성화하고 간단한 파일 이름을 비디오의 src 속성에 넣습니다. Chrome 및 iPad에서 작동합니다. 저에게 놀라움을 금치 못했으며 T5가 정적 파일/컨텍스트 요청을 처리하는 방법을 살펴 보았습니다. 지금까지는 하드 라이팅 된 "비디오 src"를 @Path ("컨텍스트 :")가있는 자산으로 전환하여 확인한 두 가지 경로가있는 것만 큼 느낄 수있었습니다. 다시 Chrome에서 작동하지만 IPad에서는 작동하지 않습니다.
그래서 나는 정말로 여기에서 길을 잃는다. IPad에서 작동하도록 허용하는 "간단한 컨텍스트"요청에서이 비밀 주스는 무엇입니까? 특별한 일이 없지만 이것이 유일한 방법입니다. 문제는
솔루션 그래서
... 난 정말 내 웹 애플리케이션 컨텍스트에서 해당 VIDS 서비스를 제공 할 수 없습니다, 그것은 "범위"라는이 HTTP 헤더가 있음을 밝혀과 아이 패드 것으로, 크롬 사용 달리 비디오와 함께. "비밀 소스"는 정적 리소스 요청을위한 서블릿 핸들러가 T5가없는 동안 범위 요청을 처리하는 방법을 알고 있다는 것입니다. 여기 내 맞춤 구현은 다음과 같습니다.
OutputStream os = response.getOutputStream("video/mp4");
InputStream is = new BufferedInputStream(new FileInputStream(f));
try {
String range = request.getHeader("Range");
if(range != null && !range.equals("bytes=0-")) {
logger.info("Range response _______________________");
String[] ranges = range.split("=")[1].split("-");
int from = Integer.parseInt(ranges[0]);
int to = Integer.parseInt(ranges[1]);
int len = to - from + 1 ;
response.setStatus(206);
response.setHeader("Accept-Ranges", "bytes");
String responseRange = String.format("bytes %d-%d/%d", from, to, f.length());
logger.info("Content-Range:" + responseRange);
response.setHeader("Connection", "close");
response.setHeader("Content-Range", responseRange);
response.setDateHeader("Last-Modified", new Date().getTime());
response.setContentLength(len);
logger.info("length:" + len);
byte[] buf = new byte[4096];
is.skip(from);
while(len != 0) {
int read = is.read(buf, 0, len >= buf.length ? buf.length : len);
if(read != -1) {
os.write(buf, 0, read);
len -= read;
}
}
} else {
response.setStatus(200);
IOUtils.copy(is, os);
}
} finally {
os.close();
is.close();
}
이것은 유용한 정보입니다. Tapestry가 표준 자산 처리 코드 내에서 이것을 자동으로 처리 할 수없는 이유는 없습니다. 우리는 단지 그것이 필요하다는 것을 인식하지 못합니다. 이 수준의 정보를 JIRA에 추가하는 것이 첫 번째 단계입니다. –
우수 답변. 바로 매력처럼 작동합니다. 고마워. –