java实现视频在线播放并解决java.io.IOException: 您的主机中的软件中止了一个已建立的连接。
生活随笔
收集整理的這篇文章主要介紹了
java实现视频在线播放并解决java.io.IOException: 您的主机中的软件中止了一个已建立的连接。
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
背景:緊接著上篇文章,博主已經完成了海康攝像頭的視頻截取,現在則需要實現視頻播放功能。
思路:前端使用video標簽,訪問后端視頻接口地址,并附帶視頻路徑參數,進行播放(后端接口需要支持分段,否則前端視頻不能拖動進度條)。
第一步:完成后端方法。
public void play(String path, HttpServletRequest request, HttpServletResponse response) { String fileName ="測試.mp4";RandomAccessFile targetFile = null;OutputStream outputStream = null;try {outputStream = response.getOutputStream();response.reset();//獲取請求頭中Range的值String rangeString = request.getHeader("Range");//打開文件File file = new File(path);if (file.exists()) {//使用RandomAccessFile讀取文件targetFile = new RandomAccessFile(file, "r");long fileLength = targetFile.length();long requestSize = (int)fileLength;//分段下載視頻if (StringUtils.hasText(rangeString)) {//從Range中提取需要獲取數據的開始和結束位置long requestStart = 0, requestEnd = 0;String[] ranges = rangeString.split("=");if (ranges.length > 1) {String[] rangeDatas = ranges[1].split("-");requestStart = Integer.parseInt(rangeDatas[0]);if (rangeDatas.length > 1) {requestEnd = Integer.parseInt(rangeDatas[1]);}}if (requestEnd != 0 && requestEnd > requestStart) {requestSize = requestEnd - requestStart + 1;}//根據協議設置請求頭response.setHeader(HttpHeaders.ACCEPT_RANGES, "bytes");response.setHeader(HttpHeaders.CONTENT_TYPE, "video/mp4");if (!StringUtils.hasText(rangeString)) {response.setHeader(HttpHeaders.CONTENT_LENGTH, fileLength + "");} else {long length;if (requestEnd > 0) {length = requestEnd - requestStart + 1;response.setHeader(HttpHeaders.CONTENT_LENGTH, "" + length);response.setHeader(HttpHeaders.CONTENT_RANGE,"bytes " + requestStart + "-" + requestEnd + "/" + fileLength);} else {length = fileLength - requestStart;response.setHeader(HttpHeaders.CONTENT_LENGTH, "" + length);response.setHeader(HttpHeaders.CONTENT_RANGE,"bytes " + requestStart + "-" + (fileLength - 1) + "/" + fileLength);}}//文段下載視頻返回206response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);//設置targetFile,從自定義位置開始讀取數據targetFile.seek(requestStart);} else {//如果Range為空則下載整個視頻response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + fileName + "");//設置文件長度response.setHeader(HttpHeaders.CONTENT_LENGTH, String.valueOf(fileLength));}//從磁盤讀取數據流返回byte[] cache = new byte[4096];try {while (requestSize > 0) {int len = targetFile.read(cache);if (requestSize < cache.length) {outputStream.write(cache, 0, (int)requestSize);} else {outputStream.write(cache, 0, len);if (len < cache.length) {break;}}requestSize -= cache.length;}} catch (IOException e) {}} else {throw new RuntimeException("文件路勁有誤");}outputStream.flush();} catch (Exception e) {} finally {if (outputStream != null) {try {outputStream.close();} catch (IOException e) {}}if (targetFile != null) {try {targetFile.close();} catch (IOException e) {}}}}第二步:完成前端
<template><div class="video-monitor-wrapper"><video width="100%" id="see" controls="controls"><source src="接口地址" type="video/mp4" /></video></div> </template>大坑注意:正常情況到這里就已經正常播放視頻了,但是博主卻發現了一個問題,我本地錄制的視頻可以播放,從攝像頭截取下來的視頻卻不可以播放,點擊播放時后臺一直報java.io.IOException: 您的主機中的軟件中止了一個已建立的連接,這種情況一般是前端主動斷開連接造成的。
百思不得其解時突然想到是不是視頻的問題,果然,發現視頻監控截取下來的雖然是.mp4后綴,但是視頻編碼是MPEG-PS的編碼格式,而vdieo標簽目前只支持三種視頻格式
?由于前端不能播放這種視頻,所以主動斷開了鏈接,所以這里有涉及到了視頻轉碼。
首先引入依賴:
<dependency><groupId>org.bytedeco</groupId><artifactId>javacv</artifactId><version>1.4.1</version></dependency><dependency><groupId>org.bytedeco</groupId><artifactId>javacpp</artifactId><version>1.4.1</version></dependency>編寫轉碼工具類
package com.video.tool.hik;import cn.hutool.http.HttpUtil; import org.bytedeco.javacpp.avcodec; import org.bytedeco.javacv.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory;/*** 視頻轉碼工具類*/ public class VideoEncodeUtil {/*** @param inputFile 文件原始路徑* @param outputFile 文件輸出路徑* @param id* @throws Exception*/public static void encode(String inputFile, String outputFile, String id) throws Exception {final Logger logger = LoggerFactory.getLogger(DownLoadCallBack.class);FFmpegFrameGrabber grabber = FFmpegFrameGrabber.createDefault(inputFile);Frame captured_frame;FFmpegFrameRecorder recorder = null;try {grabber.start();recorder = new FFmpegFrameRecorder(outputFile, grabber.getImageWidth(), grabber.getImageHeight(),grabber.getAudioChannels());recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);recorder.setFormat("mp4");recorder.setFrameRate(grabber.getFrameRate());recorder.setSampleRate(grabber.getSampleRate());recorder.setVideoBitrate(grabber.getVideoBitrate());recorder.setAspectRatio(grabber.getAspectRatio());recorder.setAudioBitrate(grabber.getAudioBitrate());recorder.setAudioOptions(grabber.getAudioOptions());recorder.setAudioCodec(avcodec.AV_CODEC_ID_AAC);recorder.start();while (true) {captured_frame = grabber.grabFrame();if (captured_frame == null) {logger.info("轉碼成功");break;}recorder.record(captured_frame);}} catch (FrameRecorder.Exception e) {e.printStackTrace();} finally {if (recorder != null) {try {recorder.close();} catch (Exception e) {logger.info("recorder.close異常");}}try {grabber.close();} catch (FrameGrabber.Exception e) {logger.info("frameGrabber.close異常");}}} }總結
以上是生活随笔為你收集整理的java实现视频在线播放并解决java.io.IOException: 您的主机中的软件中止了一个已建立的连接。的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 后端:推荐九款Java 性能优化工具,你
- 下一篇: python数字转日期函数_【转】Pyt