FFMPEG 保持文件大小的最佳参数

FFMPEG 保持文件大小的最佳参数

所以这个想法是:我想将 1 TB 驱动器中的每个视频都转换为 Chromecast 可以播放的格式(https://developers.google.com/cast/docs/media),然后我会很高兴地让我的不是那么新的 PC 工作几天(几周?)来完成它。太好了,FFMPEG 拯救了我们。

一点背景知识:我是一名 Android/Java 开发人员(在 StackOverflow 上非常活跃),我知道在某些时候我只需要编写一些批处理脚本或快速 java 命令行(因为我更喜欢 Java)来完成这项工作,但我仍然不确定在我的 FFMPEG 命令行中使用哪些参数。

所以我的需求是: - 视频编解码器:H.264 High Profile Level 5 - 音频编解码器:HE-AAC、LC-AAC、MP3 中的任意一种(老实说我不知道​​它们之间有什么区别,也许某些 AAC 会更好?)保持不变 - 我当然想使用慢速或更慢的(为了获得更好的质量) - 我当然想使用具有可变比特率的 2-pass(为了获得更好的质量)

以上所有内容都是我在教程和手册上看到的如何实现的,现在我真的不确定如何实现的部分:

我希望最终文件大小与原始文件大小大致相同。这是因为驱动器大约已满 80%,我不想通过简单地转换内容来填满它。在脚本中,我将重新编码文件并删除原始文件,这样一切就会继续进行而不会出现问题。

那么如何从文件大小获取视频比特率和音频比特率并将其放入脚本中?

附言:如果有人知道如何完成同样的工作,我同样乐意使用手刹。

先谢谢您的帮助。

答案1

您需要的 ffmpeg 命令类似于:

ffmpeg -i input.foo -c:v libx264 -profile:v high -level 5 -preset slow -b:v $videobitrate -an -pass 1 output.bar;
ffmpeg -y -i input.foo -c:v libx264 -profile:v high -level 5 -preset slow -b:v $videobitrate -b:a $audiobitrate -pass 2 output.bar

libx264 是 h264 编码器,所有选项都从 ffmpeg 传递给它,它们非常直观。第一遍不需要音频,因此需要 -an。如果需要,您可以将输出通过管道传输到 /dev/null,但随便吧。我只是在第二遍中使用了 -y 开关,这样它就会覆盖临时文件而无需询问。默认情况下,音频编解码器是 aac,因此您不必指定它。

ffprobe可以帮助您获取 $videobitrate 和 $audiobitrate 的值(我假设是 posix 环境,否则它将是 %videobitrate% 和 %audiobitrate%)。您必须执行一些 sed、awk 或 perl voodoo 才能将值转换为您可以使用的形式。以下是我机器上随机 mp4 上的 ffprobe 输出:

ffprobe version 2.1.3 Copyright (c) 2007-2013 the FFmpeg developers
  built on Feb 12 2014 22:10:38 with Apple LLVM version 5.0 (clang-500.2.79) (based on LLVM 3.3svn)
  configuration: --prefix=/usr/local/Cellar/ffmpeg/2.1.3 --enable-shared --enable-pthreads --enable-gpl --enable-version3 --enable-nonfree --enable-hardcoded-tables --enable-avresample --enable-vda --cc=clang --host-cflags= --host-ldflags= --enable-libx264 --enable-libfaac --enable-libmp3lame --enable-libxvid --enable-libfreetype --enable-libtheora --enable-libvorbis --enable-libvpx --enable-librtmp --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libvo-aacenc --enable-libass --enable-ffplay --enable-libspeex --enable-libschroedinger --enable-libfdk-aac --enable-openssl --enable-libopus --enable-frei0r --enable-libcaca --enable-libopenjpeg --extra-cflags='-I/usr/local/Cellar/openjpeg/1.5.1/include/openjpeg-1.5 '
  libavutil      52. 48.101 / 52. 48.101
  libavcodec     55. 39.101 / 55. 39.101
  libavformat    55. 19.104 / 55. 19.104
  libavdevice    55.  5.100 / 55.  5.100
  libavfilter     3. 90.100 /  3. 90.100
  libavresample   1.  1.  0 /  1.  1.  0
  libswscale      2.  5.101 /  2.  5.101
  libswresample   0. 17.104 /  0. 17.104
  libpostproc    52.  3.100 / 52.  3.100
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'loop.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : Lavf55.19.104
  Duration: 00:00:19.56, start: 0.000000, bitrate: 201 kb/s
    Stream #0:0(eng): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 400x226 [SAR 226:225 DAR 16:9], 129 kb/s, 25 fps, 25 tbr, 12800 tbn, 50 tbc (default)
    Metadata:
      handler_name    : VideoHandler
    Stream #0:1(und): Audio: aac (mp4a / 0x6134706D), 44100 Hz, mono, fltp, 75 kb/s (default)
    Metadata:
      handler_name    : SoundHandler

令人讨厌的是,ffprobe 会将所有东西都转储到 stderr,因此您需要将其重定向到 stdout。我不会告诉你如何吸鸡蛋,你的 sed-fu 可能比我的更好,但对于那些迟到的人为了获得上面例子中整个过程的比特率,你可以这样做:

videobitrate=$(ffprobe input.foo 2>&1|grep bitrate |sed "s/.*bitrate: \([0-9]*\) \([km]*\).*/\1\2/")

音频部分:

audiobitrate=$(ffprobe input.foo 2>&1|grep Audio|sed "s/.* \([0-9]*\) \([km]*\)b\/s.*/\1\2/")

不确定为什么指定了音频的比特率,但没有指定视频的比特率,可能是因为我通常使用恒定速率因子(恒定质量而不是恒定比特率)进行压缩。您必须检查电影的 ffprobe 输出。然后由您将其转换为所需的变量。请注意,ffmpeg 将解析 100k 或 3m 之类的数字。

相关内容