ffmpeg在写入视频文件时将视频转换为图像

时间:2015-10-15 02:18:52

标签: file video ffmpeg mpeg

希望ffmpeg专家提出一个简单的问题!

我目前正在将大型(+ 6GB)mpeg视频转换为图像序列 - 使用以下ffmpeg命令可以正常运行:

  

ffmpeg -i“input.mpeg”-vf - fps = fps = 2 -f image2 -qscale 1 -s 1026x768   “输出%6d.jpg”

但是我必须等待文件在我启动ffmpeg之前完成写入磁盘 - 但这需要一个小时左右来完成写入,但我注意到的是ffmpeg可以开始读取文件而它被写入磁盘 - 这里唯一的障碍是它到达文件的末尾并在文件写完之前停止...

问题是,有没有一种方法可以将ffmpeg以与写入视频相同的速度转换为图像序列(并且不会退出?)...或者知道等待下一帧写入资源。 (不幸的是输入不支持流媒体,我只得到一个网络驱动器和文件来解决..)我以为我读到某个地方,ffmpeg可以处理视频帧速率,但似乎无法找到这个命令的爱情或金钱doco !!

谢谢!

1 个答案:

答案 0 :(得分:1)

您需要替换函数调用ffmpeg用于读取文件,文件将重试,直到文件写完为止。

首先,您可以编写自己的处理器并向ffio_init_context()提供回调,该回调将重试读取,直到文件完全写入为止(您必须确定一种方法,以便您的函数能够告诉您文件已完成。)

其次,您可以确定调用ffmpeg用于读取文件的函数(可能是read()fread())并使用LD_PRELOAD来插入将在文件完成之前重试的替换项正在写它有点hackish但它可以工作。像这样的东西(这只是袖手旁观的代码,用来展示你如何做到这一点。如果你很幸运,这甚至可以起作用......):

read.c:

// most libc implementations also provide another symbol
// for library functions that starts with "_"
extern ssize_t _read( int, void *, size-t );

ssize_t read( int fd, void *buffer, size_t bytes )
{
    ssize_t bytesRead;
    for ( ;; )
    {
        bytesRead = _read( fd, buffer, bytes );
        if ( bytesRead != 0 || fileIsComplete( fd ) )
        {
            break;
        }
    }

    return ( bytesRead );
}

您需要实现fileIsComplete()以检查文件是否已完全写入 - 如果文件未完成,请将其设为sleep一小段,或者您将只是像疯了似的旋转。如果ffmpeg未使用read(),则您必须弄清楚它的用途,例如fread()

如果libc没有ffmpeg用于读取文件的函数的替代下划线前缀符号,则必须执行以下操作(示例适用于fread()

fread.c:

// function pointer to the real fread() function
static size_t (*real_fread)( void *, size_t, size_t, FILE *) = NULL;

size_t fread( void *buffer, size_t size, size_t n, FILE *stream )
{
    // might need to mutex this for multithreaded apps
    if ( real_fread == NULL )
    {
        real_fread = dlsym( RTLD_NEXT, "fread" );
    }

    size_t result;

    for ( ;; )
    {
        result = real_fread( buffer, size, n, stream );
        if ( ( result != 0 ) || fileIsComplete( stream ) )
        {
            break;
        }
    }

    return( result );
}

只需将插入的C代码编译成共享对象,并使用LD_PRELOAD让ffmpeg使用插入的read()函数。请注意,在这两种情况下,您都必须添加正确的头文件(或者可能会跳过它们,因为您可能会遇到重新声明错误 - 在这种情况下,您可能必须自己为RTLD_NEXT这样的值提供正确的定义。)

这样做可能很难正常工作,因为所有对您的插入功能的调用将通过您的库进行与LD_PRELOAD集一起运行的任何进程。您可能最好使用包装器脚本来设置LD_PRELOAD,然后运行ffmpeg,这样您只需要处理使ffmpeg与您的插入库一起工作。

并且ffmpeg可能无法很好地处理部分读取 - 您可能必须修改代码以继续读取,直到文件完成或读取了一定数量的字节,例如请求的字节数。