ffmpeg命令将原始数据复制到MP4时挂起并且永远无法完成

时间:2019-05-26 14:41:00

标签: ffmpeg

我正在运行一个ffmpeg命令,将原始H.265数据复制到MP4文件中,该命令从未完成。该文件不大,只有10秒钟的数据价值。这是我正在运行的命令:

$ ffmpeg -rtsp_transport tcp -i rtsp://user:pass@71.185.124.195:554/c1/b1558830329/e1558830339/replay/ -vcodec copy -y test_clip.mp4

然后我得到这样的输出:

ffmpeg version 3.4.6-0ubuntu0.18.04.1 Copyright (c) 2000-2019 the FFmpeg developers
  built with gcc 7 (Ubuntu 7.3.0-16ubuntu3)
  configuration: --prefix=/usr --extra-version=0ubuntu0.18.04.1 --toolchain=hardened --libdir=/usr/lib/x86_64-linux-gnu --incdir=/usr/include/x86_64-linux-gnu --enable-gpl --disable-stripping --enable-avresample --enable-avisynth --enable-gnutls --enable-ladspa --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libcdio --enable-libflite --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libgme --enable-libgsm --enable-libmp3lame --enable-libmysofa --enable-libopenjpeg --enable-libopenmpt --enable-libopus --enable-libpulse --enable-librubberband --enable-librsvg --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libssh --enable-libtheora --enable-libtwolame --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx265 --enable-libxml2 --enable-libxvid --enable-libzmq --enable-libzvbi --enable-omx --enable-openal --enable-opengl --enable-sdl2 --enable-libdc1394 --enable-libdrm --enable-libiec61883 --enable-chromaprint --enable-frei0r --enable-libopencv --enable-libx264 --enable-shared
  libavutil      55. 78.100 / 55. 78.100
  libavcodec     57.107.100 / 57.107.100
  libavformat    57. 83.100 / 57. 83.100
  libavdevice    57. 10.100 / 57. 10.100
  libavfilter     6.107.100 /  6.107.100
  libavresample   3.  7.  0 /  3.  7.  0
  libswscale      4.  8.100 /  4.  8.100
  libswresample   2.  9.100 /  2.  9.100
  libpostproc    54.  7.100 / 54.  7.100
Guessed Channel Layout for Input Stream #0.1 : mono
Input #0, rtsp, from 'rtsp://user:pass@71.85.104.195:554/c1/b1558830329/e1558830339/replay/':
  Metadata:
    title           : ONVIF RTSP Server
  Duration: N/A, start: 0.000000, bitrate: N/A
    Stream #0:0: Video: h264 (High), yuvj420p(pc, bt709, progressive), 1920x1080, 30 fps, 30 tbr, 90k tbn, 60 tbc
    Stream #0:1: Audio: pcm_mulaw, 8000 Hz, mono, s16, 64 kb/s
Stream mapping:
  Stream #0:0 -> #0:0 (copy)
  Stream #0:1 -> #0:1 (pcm_mulaw (native) -> aac (native))
Press [q] to stop, [?] for help
[aac @ 0x55b71ce31900] Too many bits 8832.000000 > 6144 per frame requested, clamping to max
Output #0, mp4, to 'test_clip.mp4':
  Metadata:
    title           : ONVIF RTSP Server
    encoder         : Lavf57.83.100
    Stream #0:0: Video: h264 (High) (avc1 / 0x31637661), yuvj420p(pc, bt709, progressive), 1920x1080, q=2-31, 30 fps, 30 tbr, 90k tbn, 90k tbc
    Stream #0:1: Audio: aac (LC) (mp4a / 0x6134706D), 8000 Hz, mono, fltp, 48 kb/s
    Metadata:
      encoder         : Lavc57.107.100 aac
[mp4 @ 0x55b71ce17e00] Non-monotonous DTS in output stream 0:0; previous: 18000, current: 3000; changing to 18001. This may result in incorrect timestamps in the output file.
[mp4 @ 0x55b71ce17e00] Non-monotonous DTS in output stream 0:0; previous: 18001, current: 6000; changing to 18002. This may result in incorrect timestamps in the output file.
[mp4 @ 0x55b71ce17e00] Non-monotonous DTS in output stream 0:0; previous: 18002, current: 9000; changing to 18003. This may result in incorrect timestamps in the output file.
[mp4 @ 0x55b71ce17e00] Non-monotonous DTS in output stream 0:0; previous: 18003, current: 12000; changing to 18004. This may result in incorrect timestamps in the output file.
[mp4 @ 0x55b71ce17e00] Non-monotonous DTS in output stream 0:0; previous: 18004, current: 15000; changing to 18005. This may result in incorrect timestamps in the output file.
[mp4 @ 0x55b71ce17e00] Non-monotonous DTS in output stream 0:0; previous: 18005, current: 18000; changing to 18006. This may result in incorrect timestamps in the output file.
frame=   44 fps=0.0 q=-1.0 size=     256kB time=00:00:01.43 bitrate=1463.4kbits/frame=   60 fps= 57 q=-1.0 size=     512kB time=00:00:01.96 bitrate=2132.9kbits/frame=   76 fps= 48 q=-1.0 size=     768kB time=00:00:02.50 bitrate=2516.7kbits/frame=   92 fps= 44 q=-1.0 size=    1024kB time=00:00:03.03 bitrate=2765.6kbits/frame=  108 fps= 41 q=-1.0 size=    1024kB time=00:00:03.56 bitrate=2352.0kbits/[NULL @ 0x55b71cdfa540] SEI type 5 size 2208 truncated at 1944
frame=  123 fps= 39 q=-1.0 size=    1280kB time=00:00:04.06 bitrate=2578.6kbits/frame=  139 fps= 38 q=-1.0 size=    1536kB time=00:00:04.60 bitrate=2735.5kbits/frame=  155 fps= 37 q=-1.0 size=    1536kB time=00:00:05.13 bitrate=2451.3kbits/frame=  171 fps= 36 q=-1.0 size=    1792kB time=00:00:05.66 bitrate=2590.7kbits/frame=  187 fps= 36 q=-1.0 size=    2048kB time=00:00:06.20 bitrate=2706.1kbits/frame=  203 fps= 35 q=-1.0 size=    2304kB time=00:00:06.73 bitrate=2803.2kbits/frame=  219 fps= 35 q=-1.0 size=    2304kB time=00:00:07.26 bitrate=2597.4kbits/frame=  235 fps= 34 q=-1.0 size=    2560kB time=00:00:07.80 bitrate=2688.7kbits/frame=  246 fps= 33 q=-1.0 size=    2560kB time=00:00:08.16 bitrate=2568.0kbits/frame=  267 fps= 34 q=-1.0 size=    3072kB time=00:00:08.86 bitrate=2838.3kbits/frame=  282 fps= 34 q=-1.0 size=    3072kB time=00:00:09.36 bitrate=2686.8kbits/frame=  298 fps= 33 q=-1.0 size=    3328kB time=00:00:09.90 bitrate=2753.9kbits/frame=  314 fps= 33 q=-1.0 size=    3328kB time=00:00:10.43 bitrate=2613.1kbits/^Cspeed=1.11x    

该命令永远不会完成,我需要使用Ctrl-C将其杀死。

我还尝试添加选项-nostdin -loglevel error并将其附加到命令末尾:> /dev/null 2>&1 < /dev/null,但无济于事。

我正在测试上面的代码,因为它模仿了我正在开发的实际代码,该代码利用Python包包装了对ffmpeg的调用。下面的Python代码在笔记本电脑上运行良好,但在EC2上都挂起(均为Ubuntu 18.04):

import argparse
import datetime
import ffmpeg


# ------------------------------------------------------------------------------
if __name__ == "__main__":

    # USAGE
    # $ python collect_and_store.py --rtsp rtsp://user:pass1@71.85.125.110:554 \
    #       --duration 30 --count 10

    # construct the argument parser and parse the arguments
    args_parser = argparse.ArgumentParser()
    args_parser.add_argument("--rtsp",
                             required=True,
                             type=str,
                             help="RTSP URL for video stream")
    args_parser.add_argument("--duration",
                             required=True,
                             type=int,
                             help="duration of saved clips (in seconds)")
    args_parser.add_argument("--count",
                             required=True,
                             type=int,
                             help="number of clips to save")
    args = vars(args_parser.parse_args())

    # sanity check for some of the arguments
    if not args["rtsp"].lower().startswith("rtsp://"):
        raise ValueError("Invalid input URL -- only RTSP supported")

    seconds_per_clip = args["duration"]
    start = int(datetime.datetime.now().strftime("%s"))
    end = start + seconds_per_clip
    number_of_files_to_collect = args["count"]

    while number_of_files_to_collect > 0:

        # build URL with start and end times
        # NOTE URL is for Uniview RTSP, add options for other camera types
        url = args["rtsp"] + f"/c1/b{start}/e{end}/replay/"

        # file where we'll write clip data
        temp_file = f"clip_b{start}_e{end}.mp4"

        # create the equivalent of the ffmpeg command:
        # $ ffmpeg -i <rtsp_url> -vcodec copy -y -rtsp_transport tcp <output_mp4>
        stream = ffmpeg.input(url)
        stream = ffmpeg.output(stream, temp_file,
                               **{"codec:v": "copy",
                                  "rtsp_transport": "tcp",
                                  "y": None
                                  }
                               )
        ffmpeg.run(stream)

        print(f"\n\nMP4 file created: {temp_file}")

        number_of_files_to_collect -= 1
        start = end + 1
        end = start + seconds_per_clip

1 个答案:

答案 0 :(得分:0)

我可以通过在-t命令中添加持续时间参数(ffmpeg)来解决此问题。因此,在此示例中,我没有指定RTSP URL中的开始和结束时间,而是仅包含开始时间,并通过ffmpeg选项将持续时间用作-t的参数。 10秒剪辑的命令行版本如下所示:

$ ffmpeg -rtsp_transport tcp -i rtsp://user:pass@71.185.124.195:554/c1/b1558830329/replay/ -t 00:00:10 -vcodec copy -y test_clip.mp4

我的Python脚本具有对ffmpeg的等效调用,现在是这样:

import argparse
import datetime

import ffmpeg


# ------------------------------------------------------------------------------
if __name__ == "__main__":

    # USAGE
    # $ python collect_and_store.py --rtsp rtsp://user:pass1@71.85.125.110:554 \
    #       --duration 30 --count 10

    # construct the argument parser and parse the arguments
    args_parser = argparse.ArgumentParser()
    args_parser.add_argument("--rtsp",
                             required=True,
                             type=str,
                             help="RTSP URL for video stream")
    args_parser.add_argument("--duration",
                             required=True,
                             type=int,
                             help="duration of saved clips (in seconds)")
    args_parser.add_argument("--count",
                             required=True,
                             type=int,
                             help="number of clips to save")
    args = vars(args_parser.parse_args())

    # sanity check for some of the arguments
    if not args["rtsp"].lower().startswith("rtsp://"):
        raise ValueError("Invalid input URL -- only RTSP supported")

    seconds_per_clip = args["duration"]
    start = int(datetime.datetime.now().strftime("%s"))
    end = start + seconds_per_clip
    number_of_files_to_collect = args["count"]

    while number_of_files_to_collect > 0:

        # build URL with start and end times
        # NOTE URL is for Uniview RTSP, add options for other camera types
        url = args["rtsp"] + f"/c1/b{start}/replay/"
        # url = args["rtsp"] + f"/c1/b{start}/e{end}/replay/"

        # file where we'll write clip data
        temp_file = f"clip_b{start}_e{end}.mp4"

        # create the equivalent of the ffmpeg command:
        # $ ffmpeg -i <rtsp_url> -vcodec copy -y -rtsp_transport tcp <output_mp4>
        stream = ffmpeg.input(url)
        stream = ffmpeg.output(stream, temp_file,
                               **{"codec:v": "copy",
                                  "rtsp_transport": "tcp",
                                  "t": f"00:00:{str(seconds_per_clip).zfill(2)}",
                                  "y": None
                                  }
                               )
        ffmpeg.run(stream)

        print(f"\n\nMP4 file created: {temp_file}")

        number_of_files_to_collect -= 1
        start += seconds_per_clip
        end += seconds_per_clip