Linux 中的命令行视频编辑(剪切、连接和预览)

Linux 中的命令行视频编辑(剪切、连接和预览)

我的编辑需求相当简单 - 我需要剪切一些视频,可能在它们之间插入一些 PNG,然后合并这些视频(不需要过渡、效果等)。基本上,pitivi可以做我想做的事 - 只是,我使用相机拍摄的 640x480 30 fps AVI,只要我放入这种素材几分钟,pitivi预览就会开始冻结,因此无法使用。

因此,我开始寻找 Linux 的命令行工具;我猜只有ffmpeg命令行 - 使用 ffmpeg 剪切视频 - 智库101 - 一个优秀的智库) 和mplayerSam - 在 Linux 下使用 mencoder 编辑视频文件) 是迄今为止的候选者,但我找不到我想到的用法的例子。

 

基本上,我想象有一个编码器和播放器工具(如ffmpegvs ffplay;或mencodervs mplayer) - 这样,首先,可以在命令行上直接指定编辑序列,最好使用帧分辨率 - 伪代码看起来像:

videnctool -compose --file=vid1.avi --start=00:00:30:12 --end=00:01:45:00 --file=vid2.avi --start=00:05:00:00 --end=00:07:12:25 --file=mypicture.png --duration=00:00:02:00 --file=vid3.avi --start=00:02:00:00 --end=00:02:45:10 --output=editedvid.avi

...或者,它可以有一个“播放列表”文本文件,例如:

vid1.avi      00:00:30:12 00:01:45:00 
vid2.avi      00:05:00:00 00:07:12:25 
mypicture.png -           00:00:02:00
vid3.avi      00:02:00:00 00:02:45:10 

...因此可以这样调用

videnctool -compose --playlist=playlist.txt --output=editedvid.avi

这里的想法是,所有视频都采用相同的格式 - 允许该工具避免转码,而只执行“原始复制”(mencoder复制codec: " -oac copy -ovc copy") - 或者如果没有,未压缩的音频/视频也可以(尽管会占用一些空间)。对于静态图像,该工具将使用视频文件设置的编码。

 

问题是,到目前为止我可以看到mencoder并且ffmpeg可以对单个文件进行操作;例如从单个文件中剪切单个部分,或合并文件(mencoder也有编辑决策列表 (EDL),可以用来做框架精确切割- 因此您可以定义多个剪切区域,但它又归属于单个文件)。这意味着我必须首先从各个文件(每个文件都需要磁盘上的临时文件)中剪切片段,然后将它们合并到最终的视频文件中。

然后我会想象,有一个相应的播放器工具,它可以读取与编码工具相同的命令行选项格式/播放列表文件 - 除了它不会生成输出文件,而是播放视频;例如用伪代码:

vidplaytool --playlist=playlist.txt --start=00:01:14 --end=00:03:13

...并且,如果有足够的内存,它会在 RAM 中生成低分辨率视频预览,并在窗口中播放,同时提供一些有限的交互(mplayer键盘快捷键用于播放、暂停、倒带、步进帧)。当然,我认为开始和结束时间指的是整个播放列表,并且包括播放列表中可能出现在该区域的任何文件。

因此,所有这一切的最终结果是:命令行操作;编辑时没有临时文件 - 并且在呈现最终输出时也没有临时文件(也没有转码)......我自己认为这会很好。

因此,虽然我认为以上所有内容可能有点牵强 - 是否存在任何可以近似于上述工作流程的东西?

答案1

是的,有。尝试使用名为“Melt”的应用程序。请参阅文档这里

如果您使用 Debian 衍生发行版:

apt-get install melt

答案2

好的,因为我找不到太多关于melt命令行用法的信息,这里有一些注释......(之后,请参阅这个答案)使用进程替换来欺骗需要文件的程序,并使用特定扩展名作为参数? - Unix&Linux Stack Exchange脚本示例bash通过

首先 - 有一个 Ubuntu/Debian 软件包melt(我有 Ubuntu 11.04 和 MLT melt 0.6.2);链接由@Ielton适用于“Media Lovin' Toolkit”(MLT)Wiki,它melt是 的一部分(但也是openshot的一部分kdenlive)。以下是来自其 git 的文档文本文件的链接:mltframework.org/mlt.git/tree - 文档/;请注意,维基百科上有一个关于构建脚本

目前,我遇到的最大(唯一)问题是,我找不到导出未压缩视频合成的方法(无论是作为png帧,还是某种未压缩的视频格式)。

 

首先,在命令行中,melt您可以通过帧控制播放;例如,要“创建” 15 帧长的白色空白,并使用内置播放器查看它melt,请使用

melt -blank 15

当您使用 查看时melt,您还将获得stderr内置播放器的命令行信息:

$ melt -blank 15 
+-----+ +-----+ +-----+ +-----+ +-----+ +-----+ +-----+ +-----+ +-----+
|1=-10| |2= -5| |3= -2| |4= -1| |5=  0| |6=  1| |7=  2| |8=  5| |9= 10|
+-----+ +-----+ +-----+ +-----+ +-----+ +-----+ +-----+ +-----+ +-----+
+---------------------------------------------------------------------+
|               H = back 1 minute,  L = forward 1 minute              |
|                 h = previous frame,  l = next frame                 |
|           g = start of clip, j = next clip, k = previous clip       |
|                0 = restart, q = quit, space = play                  |
+---------------------------------------------------------------------+
Current Position:         15

播放完成后melt,它不会退出 - 因此您应该键入q以退出它。

需要注意的是,在 中有所谓的“生产者”和“消费者” melt。如果没有指定,则默认的“消费者”是SDL(简单直接媒体层)窗口播放视频;因此上述命令与以下命令相同:

melt -blank 15 -consumer sdl

因此,如果我们想保存melt显示的内容,我们应该将消费者更改为支持文件格式的消费者。要获取消费者列表:

$ melt -query "consumers"
---
consumers:
  - sdl
  - sdl_audio
  - sdl_preview
  - sdl_still
  - gtk2_preview
  - avformat
  - libdv
  - xml
  - decklink
  - null
...

消费者libdv将直接输出 DV 格式的数据stdout,因此要将视频保存到.dv文件,您需要执行以下操作:

melt -blank 15 -consumer libdv > test.dv

请注意,从列出的消费者来看,我尝试过的唯一可以在另一个应用程序中打开的格式是libdv(我用作vlc另一个应用程序);但是,对于不同类型的转码,这可能会失败(例如,如果我尝试转换文件中的片段而不是空白,则.flv生成的 .dv 文件可以打开并播放vlc,但已损坏)。

 

现在編輯部分;本质上,你可以指定一系列文件名/in/out 节直接在命令行上;假设你有一个文件,video.avi--那么你可以这样做:

melt video.avi in=30 out=79 -blank 15 video.avi in=30 out=79

或者格式稍微好一点的:

melt \ 
video.avi in=30 out=79 \ 
-blank 15 \
video.avi in=30 out=79

这意味着video.avi将播放从第 30 帧到第 79 帧的视频;然后是 15 帧的空白;然后video.avi再次播放从第 30 帧到第 79 帧的序列。

.png要在视频编辑合成中使用图像(例如),请执行以下操作:

melt \
video.avi in=30 out=79 \
test.png in=0 out=15 \
video.avi in=30 out=79 \
-blank 15

请注意,对于test.pngin=参数不需要为 0 - 但是,图像将显示out-in时间;在这种情况下,最简单的方法是in=0完全省略该参数。

 

好消息是,这个编辑序列可以保存 - 或者称之为melt序列化- 到一个文件;注意序列化方式有:“简单”或 XML。例如,要将上述命令保存为“简单”序列化文件,我们只需-serialise [filename]在命令中添加开关:

$ melt video.avi in=30 out=79 -blank 15 video.avi in=30 out=79 -serialise file.melt 
Project saved as file.melt.

现在file.melt包含:

video.avi
in=30
out=79
-blank
15
video.avi
in=30
out=79

看起来,这种“简单”的序列化文件格式不包含“注释”字符 - 如果我尝试添加“ # comment”行,melt则会抱怨:“无法加载“# 条评论”'(但除此之外,似乎这一行被忽略了,并且播放仍然继续)。“ .melt”似乎是一个melt识别为简单序列化文件的扩展。

现在,为了重新播放这个序列化文件,我们原则上只需调用melt file.melt- 但是,更完整的命令行应该是:

melt melt_file:file.melt -consumer sdl

...这意味着:使用melt_file“生产者”打开file.melt,并在“消费者” sdl(窗口)上呈现其框架。

请注意,我的经验是,(比如说).flv视频在命令行上播放没有问题 - 但是,当它们在file.melt序列化文件中指定时会导致分段错误!.dv由其自己制作的视频melt似乎在file.melt...中运行良好。

 

XML 类型的序列化可以通过使用-consumer xml:开关 (代替-serialise)——因此上面的例子现在是:

melt video.avi in=30 out=79 -blank 15 video.avi in=30 out=79 -consumer xml:file.mlt

要“播放”新生成的file.mltXML 文件,现在可以直接执行melt file.mlt- 或者,更完整的命令行是:

melt xml:file.mlt -consumer sdl

...这意味着:使用xml“生产者”(请注意,以前它是消费者) 打开file.mlt,并在“消费者” sdl(窗口) 上呈现其框架。

请注意,在这种情况下,我遇到的问题是,.flv使用简单序列化文件会导致段错误的相同视频,使用 XML 序列化文件却可以正常运行!

在这种情况下,生成的file.mltXML 文件具有更多设置,例如分辨率、帧速率、编解码器信息等 - 但直接在文本编辑器中使用也更加困难:

<?xml version="1.0" encoding="utf-8"?>
<mlt root="/path/to" title="video.avi">
  <profile description="automatic" width="320" height="240" progressive="1" sample_aspect_num="1" sample_aspect_den="1" display_aspect_num="320" display_aspect_den="240" frame_rate_num="25" frame_rate_den="1" colorspace="601"/>
  <producer id="producer0" in="30" out="79">
    <property name="mlt_type">producer</property>
    <property name="aspect_ratio">1.000000</property>
    <property name="length">125</property>
    <property name="eof">pause</property>
    <property name="resource">video.avi</property>
    <property name="meta.media.nb_streams">2</property>
    <property name="meta.media.0.stream.type">video</property>
    <property name="meta.media.0.stream.frame_rate">25.000000</property>
    <property name="meta.media.0.stream.sample_aspect_ratio">0.000000</property>
    <property name="meta.media.0.codec.frame_rate">25.000000</property>
    <property name="meta.media.0.codec.pix_fmt">yuv420p</property>
    <property name="meta.media.0.codec.sample_aspect_ratio">1.000000</property>
    <property name="meta.media.0.codec.colorspace">601</property>
    <property name="meta.media.0.codec.name">mpeg4</property>
    <property name="meta.media.0.codec.long_name">MPEG-4 part 2</property>
    <property name="meta.media.0.codec.bit_rate">0</property>
    <property name="meta.media.1.stream.type">audio</property>
    <property name="meta.media.1.codec.sample_fmt">s16</property>
    <property name="meta.media.1.codec.sample_rate">22050</property>
    <property name="meta.media.1.codec.channels">1</property>
    <property name="meta.media.1.codec.name">mp2</property>
    <property name="meta.media.1.codec.long_name">MP2 (MPEG audio layer 2)</property>
    <property name="meta.media.1.codec.bit_rate">64000</property>
    <property name="seekable">1</property>
    <property name="meta.media.sample_aspect_num">1</property>
    <property name="meta.media.sample_aspect_den">1</property>
    <property name="meta.attr.title.markup"></property>
    <property name="meta.attr.author.markup"></property>
    <property name="meta.attr.copyright.markup"></property>
    <property name="meta.attr.comment.markup"></property>
    <property name="meta.attr.album.markup"></property>
    <property name="audio_index">1</property>
    <property name="video_index">0</property>
    <property name="mlt_service">avformat</property>
  </producer>
  <producer id="producer1" in="30" out="79">
    <property name="mlt_type">producer</property>
    <property name="aspect_ratio">1.000000</property>
    <property name="length">125</property>
    <property name="eof">pause</property>
    <property name="resource">video.avi</property>
    <property name="meta.media.nb_streams">2</property>
    <property name="meta.media.0.stream.type">video</property>
    <property name="meta.media.0.stream.frame_rate">25.000000</property>
    <property name="meta.media.0.stream.sample_aspect_ratio">0.000000</property>
    <property name="meta.media.0.codec.frame_rate">25.000000</property>
    <property name="meta.media.0.codec.pix_fmt">yuv420p</property>
    <property name="meta.media.0.codec.sample_aspect_ratio">1.000000</property>
    <property name="meta.media.0.codec.colorspace">601</property>
    <property name="meta.media.0.codec.name">mpeg4</property>
    <property name="meta.media.0.codec.long_name">MPEG-4 part 2</property>
    <property name="meta.media.0.codec.bit_rate">0</property>
    <property name="meta.media.1.stream.type">audio</property>
    <property name="meta.media.1.codec.sample_fmt">s16</property>
    <property name="meta.media.1.codec.sample_rate">22050</property>
    <property name="meta.media.1.codec.channels">1</property>
    <property name="meta.media.1.codec.name">mp2</property>
    <property name="meta.media.1.codec.long_name">MP2 (MPEG audio layer 2)</property>
    <property name="meta.media.1.codec.bit_rate">64000</property>
    <property name="seekable">1</property>
    <property name="meta.media.sample_aspect_num">1</property>
    <property name="meta.media.sample_aspect_den">1</property>
    <property name="meta.attr.title.markup"></property>
    <property name="meta.attr.author.markup"></property>
    <property name="meta.attr.copyright.markup"></property>
    <property name="meta.attr.comment.markup"></property>
    <property name="meta.attr.album.markup"></property>
    <property name="audio_index">1</property>
    <property name="video_index">0</property>
    <property name="mlt_service">avformat</property>
  </producer>
  <playlist id="playlist0">
    <entry producer="producer0" in="0" out="49"/>
    <blank length="16"/>
    <entry producer="producer1" in="0" out="49"/>
  </playlist>
  <tractor id="tractor0" title="video.avi" global_feed="1" in="0" out="115">
    <track producer="playlist0"/>
  </tractor>
</mlt>

答案3

ffmpeg 针对此问题的解决方案如下所示:

mkfifo temp1 temp2 temp3
ffmpeg -i input.wmv -ss 30 -to 60 -c copy output.wmv temp1 2> /dev/null & \
ffmpeg -i input2.wmv -t 60 -c copy temp2 2> /dev/null & \
ffmpeg -i input3.wmv -i image.png -filter_complex "[0:v][1:v] \
overlay=25:25:enable='between(t,0,20)'" -pix_fmt yuv420p -c:a copy temp3 2> /dev/null & \
ffmpeg -f mpegts -i "concat:temp1|temp2|temp3" -c copy output.mp4

它使用命名管道,因此无需在磁盘上创建临时文件,并允许您剪切视频片段并添加图像。

此示例使用第一个输入的时间 30-60,然后添加第二个输入的第一分钟,然后插入图像文件,然后插入整个第三个视频。

代码摘自:

ffmpeg 连接页面: https://trac.ffmpeg.org/wiki/Concatenate

超级用户页面使用 ffmpeg 剪切视频

超级用户页面https://video.stackexchange.com/questions/12105/add-an-image-in-front-of-video-using-ffmpeg

答案4

如果您需要一些非常简单的东西,那么也许您可以使用我创建的这个名为 EDITLY 的工具(使用 ffmpeg)。

以下是您使用的方法:

npm install -g editly

创建一个文件edit.json5,内容如下:

{
  defaults: {
    // editly defaults to randomizing transitions, but since you wanted no transitions, set it to null
    transition: null,
  },
  clips: [
    // cutFrom/cutTo values are in seconds
    { layers: [{ type: 'video', path: 'vid1.avi', cutFrom: 30.12, cutTo: 105 },
    { layers: [{ type: 'video', path: 'vid2.avi', cutFrom: 300, cutTo: 432.25 },
    { duration: 2, layers: [{ type: 'image', path: 'mypicture.png' },
    { layers: [{ type: 'video', path: 'vid3.avi', cutFrom: 120, cutTo: 165.1 },
  ],
}

现在运行:

editly edit.json5 --out editedvid.mp4

您可能还需要一些其他功能,如标题屏幕、文本或字幕覆盖和生成的背景。

请参阅项目页面了解更多信息:https://github.com/mifi/editly

相关内容