獲取視頻信息,截取視頻指定幀作爲封面圖

1.pom添加依賴

	    <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>
		<dependency>
			<groupId>org.bytedeco.javacpp-presets</groupId>
			<artifactId>opencv</artifactId>
			<version>3.4.1-1.4.1</version>
		</dependency>
		<dependency>
			<groupId>org.bytedeco.javacpp-presets</groupId>
			<artifactId>opencv</artifactId>
			<version>3.4.1-1.4.1</version>
			<classifier>linux-x86_64</classifier>
		</dependency>
		<dependency>
			<groupId>org.bytedeco.javacpp-presets</groupId>
			<artifactId>ffmpeg</artifactId>
			<version>3.4.2-1.4.1</version>
		</dependency>
		<dependency>
			<groupId>org.bytedeco.javacpp-presets</groupId>
			<artifactId>ffmpeg</artifactId>
			<version>3.4.2-1.4.1</version>
			<classifier>linux-x86_64</classifier>
		</dependency>

2.根據上傳的文件流,創建本地文件 - 這裏首先是先寫一個創建文件/文件夾的方法.

	/**
	 * @Description: 根據不同情況創建文件夾或者文件(適用於不同的操作平臺,注意:Linux上需要先擁有在文件夾下進行操作的權限)方法
	 * @Param: folderPath文件夾路徑(不傳遞指定文件夾則默認爲項目存儲的文件夾中,若傳遞,格式請保持爲: D:/1555555/20200605/).
	 *         fileName文件名(不傳遞指定文件名,則方法內會自動生成一個文件名).
	 *         fileType生成的文件具體格式(如果文件名自帶後綴則fileType可爲空).
	 * @return: 返回String. 文件夾路徑/文件路徑,創建的是什麼則返回什麼
	 * @Author: liu_yan
	 * @Date: 2018/11/15
	 */
	public static String operatingPlatform(String folderPath, String fileName, String fileType) {
		try {
			// 獲取分隔符,隨操作系統不同而不同
			String separator = "/";
			String userDir =System.getProperties().getProperty("user.dir").replace("\\","/") + separator;

			// 如果傳遞了文件夾路徑.則以傳遞的路徑爲基準創建文件夾(舉例:windows - D:/1555555/20200605; linux - /usr/local/20200605 )
			if (StringUtils.isNotEmpty(folderPath)) {
				userDir = folderPath;
				File file = new File(folderPath);
				if (!file.exists()) file.mkdirs();// 如果文件夾不存在,則創建(注意:如果是Linux這一步可能出錯,可能沒有文件夾創建權限,注意)
			}
			System.out.println("************文件夾路徑:"+folderPath+"************");

			/*
			 * 以下預計了幾種情況:
			 * 1.fileName爲空,fileType不爲空,則則以當前時間精確到毫秒值+當前時間的納秒值爲文件名創建文件
			 * 2.fileName不爲空. 則先判斷是否自帶後綴(如果有後綴,則不管它是否傳遞了fileType都直接用文件名,
			 * 如果沒有後綴,則用傳遞進來的fileType作爲後綴,要是fileType都沒有.那就不創建文件了.)
			 */
			boolean flag = false;
			if (StringUtils.isEmpty(fileName) && StringUtils.isNotEmpty(fileType)) {
				String yyyyMMdd = new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date());
				long nanosecond = System.nanoTime();
				fileName = yyyyMMdd + nanosecond + "." + fileType;
				userDir = userDir + fileName;
				flag = true;
			} else if (StringUtils.isNotEmpty(fileName)) {
				//檢查傳遞進來的fileName是否自帶後綴
				int lastIndexOf = fileName.lastIndexOf(".");
				if(lastIndexOf>0){//表示文件名自帶後綴
					userDir = userDir + fileName;
					flag = true;
				}else {
					if(StringUtils.isNotEmpty(fileType)){//文件名無後綴,則必須要傳遞進fileType
						userDir = userDir + fileName + "." + fileType;
						flag = true;
					}
				}
			}

			//if true表示需要創建文件
			if(flag){
				File file1 = new File(userDir);
				if (!file1.exists()) file1.createNewFile();// 如果不存在該文件,則創建
			}
			return userDir;
		} catch (Exception e) {
			e.printStackTrace();
			return "false";
		}
	}

2-1. 將後臺獲取到的上傳視頻的流,裝載到調用上面方法得到的空白文件中(生成本地文件)

String mp4= operatingPlatform("", "", "MP4");

doc.transferTo(new File(mp4));// doc - MultipartFile doc

3. 調用引入的jar包中提供的解析視頻信息的方法, 這裏僅獲取視頻寬高,及抓取視頻某一幀作爲封面圖

	public static void grabPic(InputStream file,Map<String,Object> resultMap) throws Exception{
		FFmpegFrameGrabber ff = new FFmpegFrameGrabber(file);
		ff.start();
		// 獲取到視頻寬高.
		int imageHeight = ff.getImageHeight();
		int imageWidth = ff.getImageWidth();
		resultMap.put("height", imageHeight);
		resultMap.put("width",  imageWidth);

		// 截取視頻中圖片
		String framefile = operatingPlatform("","","jpg");
		File targetFile = new File(framefile);

		int i = 0;
		Frame frame = null;
		int lenght = ff.getLengthInFrames()/2;
		while (i < lenght) {// 選取幀數
			frame = ff.grabFrame();
			if (frame.image != null) break;
			i++;
		}

		Java2DFrameConverter converter =new Java2DFrameConverter();
		BufferedImage srcBi =converter.getBufferedImage(frame);
		try {
			boolean write = ImageIO.write(srcBi, "jpg", targetFile);
			resultMap.put("relativePath",framefile);
		}catch (Exception e) {
			e.printStackTrace();
		}
		ff.stop();
	}

4.  準備一個裝載返回信息的Map, 獲取本地文件輸入流, 開始調用方法.

Map<String, Object> map = new HashMap<String, Object>();
InputStream ins = new FileInputStream(new File(mp4));
grabPic(ins, map);

 

注: 以上簡單講就是兩個方法, 一個創建本地文件,一個調用第三方提供的方法獲取視頻信息, 中間夾雜一點代碼.

    溫馨提示:  關閉IO流, 刪除創建的本地文件.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章