ehlxr 1 éve
szülő
commit
8dbc96d753

+ 43 - 29
etl-core/src/main/java/com/tzld/crawler/etl/model/vo/CrawlerVideoVO.java

@@ -108,6 +108,49 @@ public class CrawlerVideoVO {
 
     private String videoOssPath;
 
+    /**
+     * 音频地址
+     */
+    private String audioUrl;
+
+    @Override
+    public String toString() {
+        return "CrawlerVideoVO{" +
+                "userId=" + userId +
+                ", outUserId='" + outUserId + '\'' +
+                ", userName='" + userName + '\'' +
+                ", avatarUrl='" + avatarUrl + '\'' +
+                ", platform='" + platform + '\'' +
+                ", strategy='" + strategy + '\'' +
+                ", outVideoId='" + outVideoId + '\'' +
+                ", videoTitle='" + videoTitle + '\'' +
+                ", coverUrl='" + coverUrl + '\'' +
+                ", videoUrl='" + videoUrl + '\'' +
+                ", duration=" + duration +
+                ", publishTime='" + publishTime + '\'' +
+                ", playCnt=" + playCnt +
+                ", likeCnt=" + likeCnt +
+                ", shareCnt=" + shareCnt +
+                ", collectionCnt=" + collectionCnt +
+                ", commentCnt=" + commentCnt +
+                ", crawlerRule='" + crawlerRule + '\'' +
+                ", width=" + width +
+                ", height=" + height +
+                ", strategyType='" + strategyType + '\'' +
+                ", coverOssPath='" + coverOssPath + '\'' +
+                ", videoOssPath='" + videoOssPath + '\'' +
+                ", audioUrl='" + audioUrl + '\'' +
+                '}';
+    }
+
+    public String getAudioUrl() {
+        return audioUrl;
+    }
+
+    public void setAudioUrl(String audioUrl) {
+        this.audioUrl = audioUrl;
+    }
+
     public String getStrategyType() {
         return strategyType;
     }
@@ -156,35 +199,6 @@ public class CrawlerVideoVO {
         this.platform = platform;
     }
 
-    @Override
-    public String toString() {
-        return "CrawlerVideoVO{" +
-                "userId=" + userId +
-                ", outUserId='" + outUserId + '\'' +
-                ", userName='" + userName + '\'' +
-                ", avatarUrl='" + avatarUrl + '\'' +
-                ", platform='" + platform + '\'' +
-                ", strategy='" + strategy + '\'' +
-                ", outVideoId='" + outVideoId + '\'' +
-                ", videoTitle='" + videoTitle + '\'' +
-                ", coverUrl='" + coverUrl + '\'' +
-                ", videoUrl='" + videoUrl + '\'' +
-                ", duration=" + duration +
-                ", publishTime='" + publishTime + '\'' +
-                ", playCnt=" + playCnt +
-                ", likeCnt=" + likeCnt +
-                ", shareCnt=" + shareCnt +
-                ", collectionCnt=" + collectionCnt +
-                ", commentCnt=" + commentCnt +
-                ", crawlerRule='" + crawlerRule + '\'' +
-                ", width=" + width +
-                ", height=" + height +
-                ", strategyType='" + strategyType + '\'' +
-                ", coverOssPath='" + coverOssPath + '\'' +
-                ", videoOssPath='" + videoOssPath + '\'' +
-                '}';
-    }
-
     public String getCoverOssPath() {
         return coverOssPath;
     }

+ 25 - 10
etl-core/src/main/java/com/tzld/crawler/etl/service/impl/EtlServiceImpl.java

@@ -126,7 +126,7 @@ public class EtlServiceImpl implements EtlService {
                 return;
             }
 
-            // 2.视频文件下载、上传 OSS、清理视频信息
+            // 2.音频、视频文件下载、合成,上传 OSS、清理视频信息
             // 3.视频封面下载、上传 OSS、清理视频信息
             processVideo(data);
 
@@ -239,14 +239,26 @@ public class EtlServiceImpl implements EtlService {
         String title = data.getVideoTitle();
         String platform = data.getPlatform();
         String strategy = data.getStrategy();
+        String audioUrl = data.getAudioUrl();
 
-        // 视频文件下载、上传 OSS
-        String videoPath = url2oss(data.getVideoUrl(), "longvideo/crawler_local/data", title, platform, strategy);
-        data.setVideoOssPath(videoPath);
+        String videoPath = urlDownload(data.getVideoUrl(), "longvideo/crawler_local/data", title);
+        // 音、视频合成
+        if (!Strings.isNullOrEmpty(audioUrl)) {
+            String auditPath = urlDownload(data.getAudioUrl(), "longvideo/crawler_local/audit", title);
+            VideoUtils.videoCompose(downloadPath + File.separator + videoPath, downloadPath + File.separator + auditPath, videoPath + "_comp");
+            // 清理未合成音频的视频文件
+            Files.deleteIfExists(Paths.get(new File(downloadPath + File.separator + videoPath).getPath()));
+            videoPath += "_comp";
+        }
+
+        // 视频上传 oss
         String tempFilePath = downloadPath + File.separator + videoPath;
+        file2oss(tempFilePath, videoPath, platform, strategy);
+        data.setVideoOssPath(videoPath);
         if (data.getDuration() == null || data.getDuration() <= 0
                 || data.getWidth() == null || data.getWidth() <= 0
                 || data.getHeight() == null || data.getHeight() <= 0) {
+            // 获取视频时长、宽、高
             VideoInfoDto videoInfo = VideoUtils.getVideoInfo(tempFilePath, ffprobePath);
             if (videoInfo != null) {
                 data.setDuration(videoInfo.getDuration());
@@ -260,7 +272,8 @@ public class EtlServiceImpl implements EtlService {
         Files.deleteIfExists(Paths.get(new File(tempFilePath).getPath()));
 
         // 视频封面下载、上传 OSS
-        String coverPath = url2oss(data.getCoverUrl(), "longvideo/crawler_local/image", title, platform, strategy);
+        String coverPath = urlDownload(data.getCoverUrl(), "longvideo/crawler_local/image", title);
+        file2oss(downloadPath + File.separator + coverPath, coverPath, platform, strategy);
         data.setCoverOssPath(coverPath);
         tempFilePath = downloadPath + File.separator + videoPath;
 
@@ -269,7 +282,7 @@ public class EtlServiceImpl implements EtlService {
         Files.deleteIfExists(Paths.get(new File(tempFilePath).getPath()));
     }
 
-    private String url2oss(String fileUrl, String filePath, String title, String crawler, String mode) throws IOException {
+    private String urlDownload(String fileUrl, String filePath, String title) {
         String titleMmd5 = MD5Util.md5(title);
         String curDate = LocalDate.now().format(DateTimeFormatter.BASIC_ISO_DATE);
         String videoFilePath = filePath + File.separator + env + File.separator + curDate;
@@ -298,12 +311,14 @@ public class EtlServiceImpl implements EtlService {
             throw new CommonException(ExceptionEnum.SYSTEM_ERROR, "download file " + fileUrl + " failed!");
         }
 
+        return videoFilePath + File.separator + titleMmd5;
+    }
+
+    private void file2oss(String localFile, String ossBucketKey, String crawler, String mode) throws IOException {
         // 文件上传 OSS
         slsService.log("message", "开始上传视频... ", "crawler", crawler, "mode", mode);
-        log.info("begin upload: {}/{} to oss key: {}/{}", localFilePath, titleMmd5, videoFilePath, titleMmd5);
-        aliyunOssManager.putObject(ossBucket, videoFilePath + File.separator + titleMmd5, Files.newInputStream(Paths.get(localFilePath + File.separator + titleMmd5)));
-
-        return videoFilePath + File.separator + titleMmd5;
+        log.info("begin upload: {} to oss key: {}", localFile, ossBucketKey);
+        aliyunOssManager.putObject(ossBucket, ossBucketKey, Files.newInputStream(Paths.get(localFile)));
     }
 
     @PostConstruct

+ 21 - 2
etl-core/src/main/java/com/tzld/crawler/etl/util/VideoUtils.java

@@ -26,7 +26,9 @@ package com.tzld.crawler.etl.util;
 
 import com.tzld.crawler.etl.model.dto.VideoInfoDto;
 import net.bramp.ffmpeg.FFmpeg;
+import net.bramp.ffmpeg.FFmpegExecutor;
 import net.bramp.ffmpeg.FFprobe;
+import net.bramp.ffmpeg.builder.FFmpegBuilder;
 import net.bramp.ffmpeg.probe.FFmpegFormat;
 import net.bramp.ffmpeg.probe.FFmpegProbeResult;
 import net.bramp.ffmpeg.probe.FFmpegStream;
@@ -63,10 +65,27 @@ public class VideoUtils {
 
     public static void videoCompose(String videoPath, String audioPath, String outPath) {
         try {
-            FFmpeg ffmpeg = new FFmpeg("ffmpeg");
-            // ffmpeg.
+            FFmpeg fFmpeg = new FFmpeg("ffmpeg");
+            FFprobe fFprobe = new FFprobe("ffprobe");
+
+            FFmpegBuilder builder = new FFmpegBuilder()
+                    .setInput(videoPath)     // 主输入为视频文件
+                    .addExtraArgs("-i", audioPath)  // 然后添加音频文件作为参数
+                    .addOutput(outPath)   // 输出文件
+                    .addExtraArgs("-c:v", "copy")  // 使用原视频的编码
+                    .addExtraArgs("-c:a", "aac")  // 音频用aac编码
+                    .addExtraArgs("-strict", "experimental")
+                    .addExtraArgs("-map", "0:v:0")  //  映射视频流
+                    .addExtraArgs("-map", "1:a:0")  //  映射音频流
+                    .done();
+            FFmpegExecutor executor = new FFmpegExecutor(fFmpeg, fFprobe);
+            executor.createJob(builder).run(); // 执行 ffmpeg 命令
         } catch (IOException e) {
             throw new RuntimeException(e);
         }
     }
+
+    public static void main(String[] args) {
+        videoCompose("", "", "");
+    }
 }