Java 實現壓縮圖片,影片,音訊案例

ghostmen發表於2024-03-21

Java 實現壓縮圖片,影片,音訊案例

在 Java 中,要實現影片壓縮通常需要使用外部的庫或工具,因為 Java 標準庫本身並不提供直接的影片處理功能。以下是一些常用的方法和工具來壓縮影片:

FFmpeg:

FFmpeg 是一個開源跨平臺的多媒體處理工具,可以用來對音訊、影片等多媒體資料進行編解碼、轉換和流處理。你可以透過 Java 呼叫 FFmpeg 的命令列來實現影片壓縮。

Xuggler:

Xuggler 是一個 Java 語言的多媒體處理庫,基於 FFmpeg 和 X264 構建,提供了 Java API 來進行影片和音訊的處理。你可以使用 Xuggler 來實現影片的壓縮和轉換。

JCodec:

JCodec 是一個專門用於影片編解碼的 Java 庫,支援常見的影片編解碼格式,包括 H.264、MPEG-4 等。你可以使用 JCodec 來實現影片的壓縮和編解碼操作。


接下來我們使用FFmpeg實現音訊及影片的壓縮

匯入Maven依賴

<dependency>
    <groupId>com.vaadin.external.google</groupId>
    <artifactId>android-json</artifactId>
    <version>0.0.20131108.vaadin1</version>
    <scope>compile</scope>
</dependency>

引數說明

1. ffmpegPath:FFmpeg可執行檔案的路徑。
2. "-i", inputFile.getAbsolutePath():指定輸入檔案的路徑。
3. "-c:v", "libx264":指定影片編解碼器為libx264。
4. "-crf", "28":設定影片的質量,數值越小,影片質量越高,推薦範圍是18-28。
5. "-preset", "fast":設定編碼速度和質量的平衡,"fast"為快速編碼。
6. "-c:a", "aac":指定音訊編解碼器為AAC。
7. "-b:a", "64k":設定音訊位元率為64kbps。
8. "-movflags", "+faststart":對生成的MP4檔案進行最佳化,使其能夠逐步播放。
9. outputFile.getAbsolutePath() + ".mp4":指定輸出檔案的路徑和檔名,同時指定了輸出檔案的格式為MP4。

壓縮影片

//壓縮影片
public static void compressVideo(File inputFile, File outputFile) {
	Long startTime = System.currentTimeMillis();
	try {
		String ffmpegPath = "D:\\develop\\ffmpeg-master-latest-win64-gpl\\bin\\ffmpeg.exe"; 
		// FFmpeg可執行檔案路徑
		// 構建FFmpeg命令
		String[] command = {
			ffmpegPath,
			"-i", inputFile.getAbsolutePath(),
			"-c:v", "libx264",
			"-crf", "28",
			"-preset", "fast",
			"-c:a", "aac",
			"-b:a", "64k",
			"-movflags", "+faststart",
			outputFile.getAbsolutePath() + ".mp4"
		};
		// 建立程序生成器
		ProcessBuilder processBuilder = new ProcessBuilder(command);
		// 重定向程序的輸入、輸出和錯誤流
		processBuilder.inheritIO();
		// 啟動程序
		Process process = processBuilder.start();

		// 等待程序完成
		process.waitFor();
		Long endTime = System.currentTimeMillis();
		System.out.println("影片壓縮完成!用時: " + (endTime - startTime));
	} catch (Exception e) {
		e.printStackTrace();
	}
}

壓縮音訊

//壓縮音訊
public static byte[] compressAudio(InputStream inputStream) {
	Long startTime = System.currentTimeMillis();
	try {
		// FFmpeg可執行檔案路徑
		String[] command = {
				"ffmpeg",
				"-i", "pipe:0",
				"-b:a", "64k",
				"-f", "mp3",
				"pipe:1"
		};
		ProcessBuilder processBuilder = new ProcessBuilder(command);
		// 重定向程序的輸入、輸出和錯誤流
		processBuilder.redirectInput(ProcessBuilder.Redirect.PIPE);
		processBuilder.redirectOutput(ProcessBuilder.Redirect.PIPE);
		processBuilder.redirectError(ProcessBuilder.Redirect.INHERIT);
		// 啟動程序
		Process process = processBuilder.start();

		// 將輸入流複製到程序的輸入流中
		Thread copyThread = new Thread(() -> {
			try {
				byte[] buffer = new byte[1024];
				int len;
				while ((len = inputStream.read(buffer)) > 0) {
					process.getOutputStream().write(buffer, 0, len);
				}
				process.getOutputStream().close();
			} catch (Exception e) {
				e.printStackTrace();
			}
		});
		copyThread.start();

		// 將程序的輸出流快取到位元組陣列輸出流中
		ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
		byte[] buffer = new byte[1024];
		int len;
		while ((len = process.getInputStream().read(buffer)) > 0) {
			byteArrayOutputStream.write(buffer, 0, len);
		}

		// 等待輸入流複製執行緒完成
		copyThread.join();
		// 等待程序完成
		process.waitFor();
		Long endTime = System.currentTimeMillis();
		System.out.println("音訊壓縮完成!用時: " + (endTime - startTime));

		// 返回壓縮後的音訊檔案資料
		return byteArrayOutputStream.toByteArray();
	} catch (Exception e) {
		e.printStackTrace();
		return null;
	}
}
實現壓縮圖片
//壓縮圖片
public static InputStream compressImage(InputStream inputStream, String outputFormat) {
    BufferedImage image = null;
    try {
        image = ImageIO.read(inputStream);
    } catch (IOException e) {
        e.printStackTrace();
    }

    int newWidth = (int) (image.getWidth() * compressionRatio);
    int newHeight = (int) (image.getHeight() * compressionRatio);

    BufferedImage compressedImage = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_RGB);

    compressedImage.createGraphics().drawImage(image.getScaledInstance(newWidth, newHeight, Image.SCALE_SMOOTH), 0, 0, null);

    ByteArrayOutputStream out = new ByteArrayOutputStream();

    try {
        ImageIO.write(compressedImage, outputFormat, out);
        out.flush();
    } catch (Exception e) {
        e.printStackTrace();
    }

    ByteArrayInputStream compressedInputStream = new ByteArrayInputStream(out.toByteArray());

    return compressedInputStream;
}

相關文章