Solución:
No estoy seguro de qué tipo de fuente está utilizando para generar su transmisión de video (cámara en vivo o un archivo de video o video de youtube o ..)
Probablemente pueda usar StreamingResponseBody (requiere Spring 4.2+). Consulte los siguientes enlaces
http://www.logicbig.com/tutorials/spring-framework/spring-web-mvc/streaming-response-body/
http://shazsterblog.blogspot.in/2016/02/asynchronous-streaming-request.html
Prueba esto –
@GetMapping("/stream1")
@ResponseBody
public StreamingResponseBody getVidoeStream1(@RequestParam String any) throws IOException {
/* do security check before connecting to stream hosting server */
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<Resource> responseEntity = restTemplate.exchange( "http://localhost:8080/stream", HttpMethod.GET, null, Resource.class );
InputStream st = responseEntity.getBody().getInputStream();
return (os) -> {
readAndWrite(st, os);
};
}
private void readAndWrite(final InputStream is, OutputStream os)
throws IOException {
byte[] data = new byte[2048];
int read = 0;
while ((read = is.read(data)) > 0) {
os.write(data, 0, read);
}
os.flush();
}
Deberia de funcionar. Puede escribir su propia implementación de readAndWrite () según sus requisitos.
Entonces, su controlador de proxy de primavera podría ser algo como esto …
@Controller
public class HttpStreamProxyController {
@RequestMapping("https://foroayuda.es/spring")
@ResponseBody
public StreamingResponseBody getSecuredHttpStream() {
if (clientIsSecured) {
//... Security information
RestTemplate restTemplate = new RestTemplate();
// get video stream by connecting to stream hosting server like this
ResponseEntity<Resource> responseEntity = restTemplate.exchange( "https://ur-to-stream", HttpMethod.GET, null, Resource.class );
InputStream st = responseEntity.getBody().getInputStream();
// Or if there is any other preferred way of getting the video stream use that. The idea is to get the video input stream
// now return a StreamingResponseBody object created by following lambda
return (os) -> {
readAndWrite(st, os);
};
} else {
return null;
}
}
}
El StreamingResponseBody devuelto por su punto final de descanso funcionará bien con HTML5, que podría ser algo así como …
<video width="320" height="240" controls>
<source src="https://foroayuda.es/spring" type="video/mp4">
Your browser does not support the video tag
</video>
Luché con este mismo problema durante días, intentando migrar mi aplicación de nodo a Spring / React. Estoy usando una raspberry pi que ejecuta Motion, que actúa como un servidor de transmisión remoto que antes podía usar el módulo de nodo mjpeg-proxy
para proxy fácilmente de la manera que OP desee. Este hilo fue el conjunto de ejemplos más útil en mi búsqueda para hacer esto en Java, sin embargo, ninguno de los ejemplos funcionó para mí. Espero que mi clase de controlador y mi componente ayuden a otros a intentar lo mismo.
Por favor tome nota de response.setContentType("multipart/x-mixed-replace; boundary=BoundaryString");
como el boundary=BoundaryString
porción fue la última pieza crítica. Abrí el depurador de Chrome mientras me conectaba directamente a la transmisión y esto estaba en los encabezados de respuesta; cuando lo copié, ¡de repente todo funcionó!
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.client.ClientHttpRequest;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import javax.servlet.http.HttpServletResponse;
import java.net.URI;
@RestController
@RequestMapping(value = "/video")
public class VideoController {
Logger log = LoggerFactory.getLogger(VideoController.class);
@RequestMapping("/oculus")
public void oculus(HttpServletResponse response) {
log.info("Calling /video/oculus...");
RestTemplate restTemplate = new RestTemplate();
restTemplate.execute(
URI.create("http://oculus:8081"),
HttpMethod.GET,
(ClientHttpRequest request) -> {},
responseExtractor -> {
response.setContentType("multipart/x-mixed-replace; boundary=BoundaryString");
IOUtils.copy(responseExtractor.getBody(), response.getOutputStream());
return null;
}
);
}
@RequestMapping("/door")
public void door(HttpServletResponse response) {
log.info("Calling /video/door...");
RestTemplate restTemplate = new RestTemplate();
restTemplate.execute(
URI.create("http://vox:9002"),
HttpMethod.GET,
clientHttpRequest -> {
clientHttpRequest.getHeaders().add(HttpHeaders.AUTHORIZATION, "Basic blahblahBase64encodedUserAndPass=");
},
responseExtractor -> {
response.setContentType("multipart/x-mixed-replace; boundary=BoundaryString");
IOUtils.copy(responseExtractor.getBody(), response.getOutputStream());
return null;
}
);
}
}
He incluido ejemplos para usar la autenticación básica de Motion, así como una transmisión desprotegida.
Ambas transmisiones están disponibles en mi aplicación usando el siguiente bit de react js
class Video extends React.Component{
render() {
return (
<div className="Content">
<p>
<img className="stream" src="https://foroayuda.es/video/oculus"/>
</p>
<p>
<img className="stream" src="/video/door"/>
</p>
</div>
);
}
}
export default Video;```
Una buena manera de hacer transmisión de video en una aplicación Spring Boot (sin embargo, usé una fuente diferente: una cámara USB):
@GetMapping(value = "/stream")
public ResponseEntity<StreamingResponseBody> stream() {
StreamingResponseBody stream = outputStream -> {
while (streaming.get()) {
final var raw = streamImage.get();
final var jpeg = convert(byte2Buffered(raw.getImageData(), raw.getImageWidth(), raw.getImageHeight()));
outputStream.write(jpeg);
}
outputStream.flush();
};
final var headers = new HttpHeaders();
headers.add("Access-Control-Allow-Origin", "*");
headers.add("Cache-Control", "no-cache, no-store, must-revalidate");
headers.add("Content-Type", "multipart/x-mixed-replace;boundary=frame");
headers.add("Expires", "0");
headers.add("Pragma", "no-cache");
headers.add("Max-Age", "0");
return ResponseEntity.ok()
.headers(headers)
.body(stream);
}
De esta manera, obtendrá una transmisión en el punto final de la URL, que puede incrustar en una página web usando img
Etiqueta HTML.