zhangyong 4 місяців тому
батько
коміт
cbe613f1ab
1 змінених файлів з 166 додано та 138 видалено
  1. 166 138
      common/ffmpeg.py

+ 166 - 138
common/ffmpeg.py

@@ -68,26 +68,29 @@ class FFmpeg():
     @classmethod
     def video_crop(cls, video_path, file_path):
         crop_url = file_path + 'crop.mp4'
-        # 获取视频的原始宽高信息
-        ffprobe_cmd = cls.asyncio_run_subprocess(
-            ["ffprobe", "-v", "error", "-select_streams", "v:0", "-show_entries", "stream=width,height", "-of",
-             "csv=p=0", video_path], timeout=10)
-        width, height = map(int, ffprobe_cmd.strip().split(','))
-        # 计算裁剪后的高度
-        new_height = int(height * 0.8)
+        try:
+            # 获取视频的原始宽高信息
+            ffprobe_cmd = cls.asyncio_run_subprocess(
+                ["ffprobe", "-v", "error", "-select_streams", "v:0", "-show_entries", "stream=width,height", "-of",
+                 "csv=p=0", video_path], timeout=10)
+            width, height = map(int, ffprobe_cmd.strip().split(','))
+            # 计算裁剪后的高度
+            new_height = int(height * 0.8)
 
-        # 构建 FFmpeg 命令,裁剪视频高度为原始高度的80%
-        cls.asyncio_run_subprocess(
-            [
-            "ffmpeg",
-            "-i", video_path,
-            "-vf", f"crop={width}:{new_height}",
-            "-c:v", "libx264",
-            "-c:a", "aac",
-            "-y",
-            crop_url
-            ],timeout=240)
-        return crop_url
+            # 构建 FFmpeg 命令,裁剪视频高度为原始高度的80%
+            cls.asyncio_run_subprocess(
+                [
+                "ffmpeg",
+                "-i", video_path,
+                "-vf", f"crop={width}:{new_height}",
+                "-c:v", "libx264",
+                "-c:a", "aac",
+                "-y",
+                crop_url
+                ],timeout=240)
+            return crop_url
+        except Exception as e:
+            return crop_url
 
     """
     视频截断
@@ -96,35 +99,39 @@ class FFmpeg():
     def video_ggduration(cls, video_path, file_path, gg_duration_total):
         gg_duration_url = file_path + 'gg_duration.mp4'
         # 获取视频时长
-        total_duration = cls.get_video_duration(video_path)
-        if total_duration == 0:
+        try:
+            total_duration = cls.get_video_duration(video_path)
+            if total_duration == 0:
+                return gg_duration_url
+            duration = int(total_duration) - int(gg_duration_total)
+            if int(total_duration) < int(gg_duration_total):
+                return gg_duration_url
+            cls.asyncio_run_subprocess([
+                "ffmpeg",
+                "-i", video_path,
+                "-c:v", "libx264",
+                "-c:a", "aac",
+                "-t", str(duration),
+                "-y",
+                gg_duration_url
+            ], timeout= 360)
             return gg_duration_url
-        duration = int(total_duration) - int(gg_duration_total)
-        if int(total_duration) < int(gg_duration_total):
+        except Exception as e:
             return gg_duration_url
-        cls.asyncio_run_subprocess([
-            "ffmpeg",
-            "-i", video_path,
-            "-c:v", "libx264",
-            "-c:a", "aac",
-            "-t", str(duration),
-            "-y",
-            gg_duration_url
-        ], timeout= 360)
-        return gg_duration_url
 
     """
      截取原视频最后一帧
     """
     @classmethod
     def video_png(cls, video_path, file_path):
-        """
-        """
         # 获取视频的原始宽高信息
         jpg_url = file_path + 'png.jpg'
-        cls.asyncio_run_subprocess(
-            ["ffmpeg", "-sseof", "-1", '-i', video_path, '-frames:v', '1',  "-y", jpg_url], timeout=120)
-        return jpg_url
+        try:
+            cls.asyncio_run_subprocess(
+                ["ffmpeg", "-sseof", "-1", '-i', video_path, '-frames:v', '1',  "-y", jpg_url], timeout=120)
+            return jpg_url
+        except Exception as e:
+            return jpg_url
 
     """
     获取视频音频
@@ -132,36 +139,48 @@ class FFmpeg():
     @classmethod
     def get_video_mp3(cls, video_file, video_path_url, pw_random_id):
         pw_mp3_path = video_path_url + str(pw_random_id) +'pw_video.mp3'
-        cls.asyncio_run_subprocess([
-            'ffmpeg',
-            '-i', video_file,
-            '-q:a', '0',
-            '-map', 'a',
-            pw_mp3_path
-        ], timeout=120)
-        time.sleep(1)
-        return pw_mp3_path
+        try:
+            cls.asyncio_run_subprocess([
+                'ffmpeg',
+                '-i', video_file,
+                '-q:a', '0',
+                '-map', 'a',
+                pw_mp3_path
+            ], timeout=120)
+            time.sleep(1)
+            return pw_mp3_path
+        except Exception as e:
+            return pw_mp3_path
 
     """横屏视频改为竖屏"""
     @classmethod
     def update_video_h_w(cls, video_path, file_path):
         video_h_w_path = file_path +'video_h_w_video.mp4'
-        cls.asyncio_run_subprocess(["ffmpeg" ,"-i" ,video_path ,"-vf" ,"scale=640:ih*640/iw,pad=iw:iw*16/9:(ow-iw)/2:(oh-ih)/2" ,video_h_w_path],timeout=420)
-        return video_h_w_path
+        try:
+            cls.asyncio_run_subprocess(["ffmpeg" ,"-i" ,video_path ,"-vf" ,"scale=640:ih*640/iw,pad=iw:iw*16/9:(ow-iw)/2:(oh-ih)/2" ,video_h_w_path],timeout=420)
+            return video_h_w_path
+        except Exception as e:
+            return video_h_w_path
 
     """视频转为640像素"""
     @classmethod
     def video_640(cls, video_path, file_path):
         video_url = file_path + 'pixelvideo.mp4'
-        cls.asyncio_run_subprocess(["ffmpeg" ,"-i" ,video_path ,"-vf" ,"scale=360:640" ,video_url],timeout=420)
-        return video_url
+        try:
+            cls.asyncio_run_subprocess(["ffmpeg" ,"-i" ,video_path ,"-vf" ,"scale=360:640" ,video_url],timeout=420)
+            return video_url
+        except Exception as e:
+            return video_url
 
     """视频拼接到一起"""
     @classmethod
     def h_b_video(cls, video_path, pw_path, file_path):
         video_url = file_path + 'hbvideo.mp4'
-        cls.asyncio_run_subprocess(["ffmpeg","-i", video_path, "-i", pw_path, "-filter_complex" ,"[0:v]scale=360:640[v1]; [1:v]scale=360:640[v2]; [v1][0:a][v2][1:a]concat=n=2:v=1:a=1[outv][outa]" ,"-map" ,"[outv]" ,"-map" ,"[outa]" ,video_url],timeout=500)
-        return video_url
+        try:
+            cls.asyncio_run_subprocess(["ffmpeg","-i", video_path, "-i", pw_path, "-filter_complex" ,"[0:v]scale=360:640[v1]; [1:v]scale=360:640[v2]; [v1][0:a][v2][1:a]concat=n=2:v=1:a=1[outv][outa]" ,"-map" ,"[outv]" ,"-map" ,"[outa]" ,video_url],timeout=500)
+            return video_url
+        except Exception as e:
+            return video_url
 
     """横屏视频顶部增加字幕"""
     @classmethod
@@ -169,31 +188,34 @@ class FFmpeg():
         single_video_srt = video_path_url + str(pw_random_id) +'video_zm.srt'
         single_video_txt = video_path_url + str(pw_random_id) +'video_zm.txt'
         single_video = video_path_url + str(pw_random_id) +'video_zm.mp4'
-        duration = cls.get_video_duration(new_video_path)
-        if duration == 0:
-            return new_video_path
-        start_time = cls.seconds_to_srt_time(0)
-        end_time = cls.seconds_to_srt_time(duration)
-        # zm = '致敬伟大的教员,为整个民族\n感谢老人家历史向一代伟人'
-        with open(single_video_txt, 'w') as f:
-            f.write(f"file '{new_video_path}'\n")
-        with open(single_video_srt, 'w') as f:
-            f.write(f"1\n{start_time} --> {end_time}\n{new_text}\n\n")
-        subtitle_cmd = f"subtitles={single_video_srt}:force_style='Fontsize=12,Fontname=wqy-zenhei,Outline=2,PrimaryColour=&H00FFFF,SecondaryColour=&H000000,Bold=1,MarginV=225'"
-        draw = f"{subtitle_cmd}"
-        cls.asyncio_run_subprocess([
-            "ffmpeg",
-            "-f", "concat",
-            "-safe", "0",
-            "-i", single_video_txt,
-            "-c:v", "libx264",
-            "-c:a", "aac",
-            "-vf", draw,
-            "-y",
-            single_video
-        ],timeout=500)
-        # subprocess.run(ffmpeg_cmd)
-        return single_video
+        try:
+            duration = cls.get_video_duration(new_video_path)
+            if duration == 0:
+                return new_video_path
+            start_time = cls.seconds_to_srt_time(0)
+            end_time = cls.seconds_to_srt_time(duration)
+            # zm = '致敬伟大的教员,为整个民族\n感谢老人家历史向一代伟人'
+            with open(single_video_txt, 'w') as f:
+                f.write(f"file '{new_video_path}'\n")
+            with open(single_video_srt, 'w') as f:
+                f.write(f"1\n{start_time} --> {end_time}\n{new_text}\n\n")
+            subtitle_cmd = f"subtitles={single_video_srt}:force_style='Fontsize=12,Fontname=wqy-zenhei,Outline=2,PrimaryColour=&H00FFFF,SecondaryColour=&H000000,Bold=1,MarginV=225'"
+            draw = f"{subtitle_cmd}"
+            cls.asyncio_run_subprocess([
+                "ffmpeg",
+                "-f", "concat",
+                "-safe", "0",
+                "-i", single_video_txt,
+                "-c:v", "libx264",
+                "-c:a", "aac",
+                "-vf", draw,
+                "-y",
+                single_video
+            ],timeout=500)
+            # subprocess.run(ffmpeg_cmd)
+            return single_video
+        except Exception as e:
+            return single_video
 
     """获取mp3时长"""
     @classmethod
@@ -223,34 +245,37 @@ class FFmpeg():
         with open(pw_srt_path, 'w') as f:
             f.write(pw_srt)
         pw_url_path = file_path + 'pw_video.mp4'
-        pw_duration = cls.get_mp3_duration(pw_mp3_path)
-        if pw_duration == 0:
-            return pw_url_path
-        time.sleep(2)
-        # 添加字幕 wqy-zenhei  Hiragino Sans GB
-        height = 1080
-        margin_v = int(height) // 8  # 可根据需要调整字幕和背景之间的距离
-        subtitle_cmd = f"subtitles={pw_srt_path}:force_style='Fontsize=13,Fontname=wqy-zenhei,Outline=0,PrimaryColour=&H000000,SecondaryColour=&H000000,Bold=1,MarginV={margin_v}'"
-        bg_position_offset = (int(360) - 360//8) / 1.75
-        background_cmd = f"drawbox=y=(ih-{int(360)}/2-{bg_position_offset}):color=yellow@1.0:width=iw:height={int(360)}/4:t=fill"
+        try:
+            pw_duration = cls.get_mp3_duration(pw_mp3_path)
+            if pw_duration == 0:
+                return pw_url_path
+            time.sleep(2)
+            # 添加字幕 wqy-zenhei  Hiragino Sans GB
+            height = 1080
+            margin_v = int(height) // 8  # 可根据需要调整字幕和背景之间的距离
+            subtitle_cmd = f"subtitles={pw_srt_path}:force_style='Fontsize=13,Fontname=wqy-zenhei,Outline=0,PrimaryColour=&H000000,SecondaryColour=&H000000,Bold=1,MarginV={margin_v}'"
+            bg_position_offset = (int(360) - 360//8) / 1.75
+            background_cmd = f"drawbox=y=(ih-{int(360)}/2-{bg_position_offset}):color=yellow@1.0:width=iw:height={int(360)}/4:t=fill"
 
-        cls.asyncio_run_subprocess([
-            'ffmpeg',
-            '-loop', '1',
-            '-i', jpg_path,  # 输入的图片文件
-            '-i', pw_mp3_path,  # 输入的音频文件
-            '-c:v', 'libx264',  # 视频编码格式
-            '-t', str(pw_duration),  # 输出视频的持续时间,与音频持续时间相同
-            '-pix_fmt', 'yuv420p',  # 像素格式
-            '-c:a', 'aac',  # 音频编码格式
-            '-strict', 'experimental',  # 使用实验性编码器
-            '-shortest',  # 确保输出视频的长度与音频一致
-            '-vf', f"{background_cmd},{subtitle_cmd}",  # 视频过滤器,设置分辨率和其他过滤器
-            pw_url_path  # 输出的视频文件路径
-        ], timeout=500)
-        if os.path.exists(pw_srt_path):
-            os.remove(pw_srt_path)
-        return pw_url_path
+            cls.asyncio_run_subprocess([
+                'ffmpeg',
+                '-loop', '1',
+                '-i', jpg_path,  # 输入的图片文件
+                '-i', pw_mp3_path,  # 输入的音频文件
+                '-c:v', 'libx264',  # 视频编码格式
+                '-t', str(pw_duration),  # 输出视频的持续时间,与音频持续时间相同
+                '-pix_fmt', 'yuv420p',  # 像素格式
+                '-c:a', 'aac',  # 音频编码格式
+                '-strict', 'experimental',  # 使用实验性编码器
+                '-shortest',  # 确保输出视频的长度与音频一致
+                '-vf', f"{background_cmd},{subtitle_cmd}",  # 视频过滤器,设置分辨率和其他过滤器
+                pw_url_path  # 输出的视频文件路径
+            ], timeout=500)
+            if os.path.exists(pw_srt_path):
+                os.remove(pw_srt_path)
+            return pw_url_path
+        except Exception as e:
+            return pw_url_path
 
 
     """
@@ -261,40 +286,43 @@ class FFmpeg():
         single_video_url = file_path + 'single_video.mp4'
         single_video_srt = file_path + 'single_video.srt'
         # 获取时长
-        duration = cls.get_video_duration(video_path)
-        if duration == 0:
+        try:
+            duration = cls.get_video_duration(video_path)
+            if duration == 0:
+                return single_video_url
+            start_time = cls.seconds_to_srt_time(2)
+            end_time = cls.seconds_to_srt_time(duration)
+            single_video_txt = file_path + 'single_video.txt'
+            with open(single_video_txt, 'w') as f:
+                f.write(f"file '{video_path}'\n")
+            if zm:
+                with open(single_video_srt, 'w') as f:
+                    f.write(f"1\n{start_time} --> {end_time}\n<font color=\"red\">\u2764\uFE0F</font>{zm}\n\n")
+                subtitle_cmd = f"subtitles={single_video_srt}:force_style='Fontsize=14,Fontname=wqy-zenhei,Outline=2,PrimaryColour=&H00FFFF,SecondaryColour=&H000000,Bold=1,MarginV=20'"
+            else:
+                subtitle_cmd = f"force_style='Fontsize=14,Fontname=wqy-zenhei,Outline=2,PrimaryColour=&H00FFFF,SecondaryColour=&H000000,Bold=1,MarginV=20'"
+            # 多线程数
+            num_threads = 5
+            # 构建 FFmpeg 命令,生成视频
+            cls.asyncio_run_subprocess([
+                    "ffmpeg",
+                    "-f", "concat",
+                    "-safe", "0",
+                    "-i",  f"{single_video_txt}",
+                    "-c:v", "libx264",
+                    "-c:a", "aac",
+                    '-b:v', '260k',
+                    "-b:a", "96k",
+                    "-threads", str(num_threads),
+                    "-vf", subtitle_cmd,
+                    "-y",
+                     single_video_url
+            ], timeout=400)
+            if os.path.exists(single_video_srt):
+                os.remove(single_video_srt)
+            return single_video_url
+        except Exception as e:
             return single_video_url
-        start_time = cls.seconds_to_srt_time(2)
-        end_time = cls.seconds_to_srt_time(duration)
-        single_video_txt = file_path + 'single_video.txt'
-        with open(single_video_txt, 'w') as f:
-            f.write(f"file '{video_path}'\n")
-        if zm:
-            with open(single_video_srt, 'w') as f:
-                f.write(f"1\n{start_time} --> {end_time}\n<font color=\"red\">\u2764\uFE0F</font>{zm}\n\n")
-            subtitle_cmd = f"subtitles={single_video_srt}:force_style='Fontsize=14,Fontname=wqy-zenhei,Outline=2,PrimaryColour=&H00FFFF,SecondaryColour=&H000000,Bold=1,MarginV=20'"
-        else:
-            subtitle_cmd = f"force_style='Fontsize=14,Fontname=wqy-zenhei,Outline=2,PrimaryColour=&H00FFFF,SecondaryColour=&H000000,Bold=1,MarginV=20'"
-        # 多线程数
-        num_threads = 5
-        # 构建 FFmpeg 命令,生成视频
-        cls.asyncio_run_subprocess([
-                "ffmpeg",
-                "-f", "concat",
-                "-safe", "0",
-                "-i",  f"{single_video_txt}",
-                "-c:v", "libx264",
-                "-c:a", "aac",
-                '-b:v', '260k',
-                "-b:a", "96k",
-                "-threads", str(num_threads),
-                "-vf", subtitle_cmd,
-                "-y",
-                 single_video_url
-        ], timeout=400)
-        if os.path.exists(single_video_srt):
-            os.remove(single_video_srt)
-        return single_video_url
 
     @classmethod
     def asyncio_run_subprocess(cls, params: List[str], timeout: int = 30) -> str: