Java ffmpeg 實現(xiàn)視頻加文字/圖片水印功能(示例代碼)
更新時間:2024年10月25日 09:17:26 作者:menghl
本文介紹了使用Java和ffmpeg庫實現(xiàn)視頻加文字或圖片水印的方法,通過引入依賴代碼和示例,詳細說明了如何將文字水印和圖片水印添加到視頻中,為需要在視頻中加入水印的開發(fā)者提供了實用的指導(dǎo),這種方法不僅增強了視頻內(nèi)容的版權(quán)保護,也為視頻編輯提供了更多的可能性
引入依賴
<dependency> <groupId>org.bytedeco</groupId> <artifactId>javacv-platform</artifactId> <version>1.5.4</version> </dependency> <dependency> <groupId>org.bytedeco</groupId> <artifactId>ffmpeg-platform</artifactId> <version>4.3.1-1.5.4</version> </dependency>
代碼示例
文字水印實現(xiàn)
import org.bytedeco.javacv.*; import org.bytedeco.javacv.Frame; import java.awt.*; import java.awt.image.BufferedImage; /** * 視頻添加文字水印 * * @author alin */ public class VideoWatermark { public static void main(String[] args) throws Exception { // 視頻文件 String inputFile = "D:\\test\\video.mp4"; // 輸出文件 String outputFile = "D:\\test\\output.mp4"; // 初始化FFmpegFrameGrabber以讀取輸入視頻文件 try (FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(inputFile)) { grabber.start(); // 初始化FFmpegFrameRecorder以寫入輸出視頻文件 try (FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(outputFile, grabber.getImageWidth(), grabber.getImageHeight(), grabber.getAudioChannels())) { recorder.setFormat("mp4"); recorder.setSampleRate(grabber.getSampleRate()); recorder.setFrameRate(grabber.getFrameRate()); recorder.setTimestamp(grabber.getTimestamp()); recorder.setVideoBitrate(grabber.getVideoBitrate()); recorder.setVideoCodec(grabber.getVideoCodec()); recorder.start(); // 處理每一幀 Frame frame; Java2DFrameConverter converter = new Java2DFrameConverter(); while ((frame = grabber.grab()) != null) { if (frame.image != null) { // 將Frame轉(zhuǎn)換為BufferedImage BufferedImage bufferedImage = converter.getBufferedImage(frame); // 在BufferedImage上繪制文字水印 Graphics2D g = bufferedImage.createGraphics(); // 啟用抗鋸齒 g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); // 啟用文本抗鋸齒 g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); // 使用支持中文的字體 g.setFont(new Font("Microsoft YaHei", Font.BOLD, 30)); g.setColor(Color.gray); String watermarkText = "測試水印文字"; // 計算水印文字的位置 右下角 //FontMetrics fontMetrics = g.getFontMetrics(); //int textWidth = fontMetrics.stringWidth(watermarkText); //int textHeight = fontMetrics.getHeight(); //int x = bufferedImage.getWidth() - textWidth - 10; // 右邊距10像素 //int y = bufferedImage.getHeight() - textHeight + fontMetrics.getAscent() - 10; // 下邊距10像素 // 計算水印文字的位置 左上角 int x = 10; // 左邊距10像素 int y = 30; // 上邊距30像素 g.drawString(watermarkText, x, y); g.dispose(); // 將BufferedImage轉(zhuǎn)換回Frame frame = converter.convert(bufferedImage); } // 記錄幀 recorder.record(frame); } // 關(guān)閉grabber和recorder recorder.stop(); recorder.release(); grabber.stop(); } } } }
圖片水印實現(xiàn)
import org.bytedeco.javacv.*; import org.bytedeco.javacv.Frame; import javax.imageio.ImageIO; import java.awt.*; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.net.URL; /** * 視頻添加圖片水印 * * @author alin */ public class VideoWatermark { public static void main(String[] args) throws Exception { // 視頻文件 String inputFile = "D:\\test\\video.mp4"; // 輸出文件 String outputFile = "D:\\test\\output.mp4"; // 水印照片 String watermarkImageUrl = "D:\\test\\test.png"; try (FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(inputFile)) { grabber.start(); try (FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(outputFile, grabber.getImageWidth(), grabber.getImageHeight(), grabber.getAudioChannels())) { recorder.setFormat("mp4"); recorder.setSampleRate(grabber.getSampleRate()); recorder.setFrameRate(grabber.getFrameRate()); recorder.setTimestamp(grabber.getTimestamp()); recorder.setVideoBitrate(grabber.getVideoBitrate()); recorder.setVideoCodec(grabber.getVideoCodec()); recorder.start(); BufferedImage watermarkImage = loadWatermarkImage(watermarkImageUrl); Frame frame; while ((frame = grabber.grab()) != null) { if (frame.image != null) { Java2DFrameConverter converter = new Java2DFrameConverter(); BufferedImage bufferedImage = converter.getBufferedImage(frame); // 在BufferedImage上繪制圖片水印 Graphics2D g = bufferedImage.createGraphics(); g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f)); int x = 10; // 左邊距10像素 int y = 30; // 上邊距30像素 g.drawImage(watermarkImage, x, y, null); g.dispose(); frame = converter.convert(bufferedImage); } recorder.record(frame); } recorder.stop(); recorder.release(); grabber.stop(); } } } /** * 加載水印圖片 * * @param imagePath 水印圖片路徑 * @return 水印圖片 * @throws IOException */ private static BufferedImage loadWatermarkImage(String imagePath) throws IOException { //return ImageIO.read(new URL(imagePath)); return ImageIO.read(new File(imagePath)); } }
到此這篇關(guān)于Java ffmpeg 實現(xiàn)視頻加文字/圖片水印功能的文章就介紹到這了,更多相關(guān)Java ffmpeg 視頻加文字內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Spring學(xué)習(xí)筆記之bean的基礎(chǔ)知識
ean在Spring和SpringMVC中無所不在,將這個概念內(nèi)化很重要,所以下面這篇文章主要給大家介紹了關(guān)于Spring學(xué)習(xí)筆記之bean基礎(chǔ)的相關(guān)資料,文中通過示例代碼介紹的非常詳解,需要的朋友可以參考下。2017-12-12autoMapping和autoMappingBehavior的區(qū)別及說明
這篇文章主要介紹了autoMapping和autoMappingBehavior的區(qū)別及說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-01-01java基本教程之Thread中start()和run()的區(qū)別 java多線程教程
這篇文章主要介紹了Thread中start()和run()的區(qū)別,Thread類包含start()和run()方法,它們的區(qū)別是什么?下面將對此作出解答2014-01-01SSM框架中測試單元的使用 spring整合Junit過程詳解
這篇文章主要介紹了SSM框架中測試單元的使用 spring整合Junit過程詳解,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2019-09-09