Newest 'libx264' Questions - Stack Overflow
Les articles publiés sur le site
-
What ffmpeg arguments will approximate Zoom recording quality [closed]
25 octobre 2020, par Stan IvanovI've been recording screen sharing presentations using Quicktime on my Mac and it uses x264 format with ~60fps. The produced video file is with type MOV and around 2.2GB for 1 hour of presentation. I want to compress it using ffmpeg and I've been doing so using x264 as well. Here are my arguments:
ffmpeg -i '$inputFile' -vcodec "libx264" -crf 32 -vf 'scale=${width}:-2,fps=24' -c:a aac -b:a 128k -preset veryslow -profile:v high -tune stillimage -f mp4 '$outputFile'
I rescale my video to 1600px width to save on space and I also convert the recording to 24fps as I see no need to have the full ~60fps available. It's mostly static images as I talk over my screen. This results in about 100MB file using the
-profile:v high
argument. Otherwise it is around 160MB.On the other hand Zoom recording for much larger resolutions (4k etc) are around ~80MB per 1 hour. Does anyone know what options we can use to approximate this file size and quality? I know they are using lower quality audio which might explain some of the difference.
But if I increase the
-crf 32
argument it starts to degrade quality too much. I am not sure how Zoom achieves it's video quality with high resolutions such as 1080p and 4k with a file size of ~80MB while I can't match it using 1600px width.Edit: I had an idea that I probably don't need all 24 fps in a screen sharing of static content. So I reduced it to 5 fps and that seems to work well for my use case. I wonder if this is what Zoom does?
-
FFMPEG RTSP stream to MPEG4/H264 file using libx264
16 octobre 2020, par PhiHeyo folks,
I'm attempting to transcode/remux an RTSP stream in H264 format into a MPEG4 container, containing just the H264 video stream. Basically, webcam output into a MP4 container.
I can get a poorly coded MP4 produced, using this code:
// Variables here for demo AVFormatContext * video_file_output_format = nullptr; AVFormatContext * rtsp_format_context = nullptr; AVCodecContext * video_file_codec_context = nullptr; AVCodecContext * rtsp_vidstream_codec_context = nullptr; AVPacket packet = {0}; AVStream * video_file_stream = nullptr; AVCodec * rtsp_decoder_codec = nullptr; int errorNum = 0, video_stream_index = 0; std::string outputMP4file = "D:\\somemp4file.mp4"; // begin AVDictionary * opts = nullptr; av_dict_set(&opts, "rtsp_transport", "tcp", 0); if ((errorNum = avformat_open_input(&rtsp_format_context, uriANSI.c_str(), NULL, &opts)) < 0) { errOut << "Connection failed: avformat_open_input failed with error " << errorNum << ":\r\n" << ErrorRead(errorNum); TacticalAbort(); return; } rtsp_format_context->max_analyze_duration = 50000; if ((errorNum = avformat_find_stream_info(rtsp_format_context, NULL)) < 0) { errOut << "Connection failed: avformat_find_stream_info failed with error " << errorNum << ":\r\n" << ErrorRead(errorNum); TacticalAbort(); return; } video_stream_index = errorNum = av_find_best_stream(rtsp_format_context, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0); if (video_stream_index < 0) { errOut << "Connection in unexpected state; made a connection, but there was no video stream.\r\n" "Attempts to find a video stream resulted in error " << errorNum << ": " << ErrorRead(errorNum); TacticalAbort(); return; } rtsp_vidstream_codec_context = rtsp_format_context->streams[video_stream_index]->codec; av_init_packet(&packet); if (!(video_file_output_format = av_guess_format(NULL, outputMP4file.c_str(), NULL))) { TacticalAbort(); throw std::exception("av_guess_format"); } if (!(rtsp_decoder_codec = avcodec_find_decoder(rtsp_vidstream_codec_context->codec_id))) { errOut << "Connection failed: connected, but avcodec_find_decoder returned null.\r\n" "Couldn't find codec with an AV_CODEC_ID value of " << rtsp_vidstream_codec_context->codec_id << "."; TacticalAbort(); return; } video_file_format_context = avformat_alloc_context(); video_file_format_context->oformat = video_file_output_format; if (strcpy_s(video_file_format_context->filename, sizeof(video_file_format_context->filename), outputMP4file.c_str())) { errOut << "Couldn't open video file: strcpy_s failed with error " << errno << "."; std::string log = errOut.str(); TacticalAbort(); throw std::exception("strcpy_s"); } if (!(video_file_encoder_codec = avcodec_find_encoder(video_file_output_format->video_codec))) { TacticalAbort(); throw std::exception("avcodec_find_encoder"); } // MARKER ONE if (!outputMP4file.empty() && !(video_file_output_format->flags & AVFMT_NOFILE) && (errorNum = avio_open2(&video_file_format_context->pb, outputMP4file.c_str(), AVIO_FLAG_WRITE, nullptr, &opts)) < 0) { errOut << "Couldn't open video file \"" << outputMP4file << "\" for writing : avio_open2 failed with error " << errorNum << ": " << ErrorRead(errorNum); TacticalAbort(); return; } // Create stream in MP4 file if (!(video_file_stream = avformat_new_stream(video_file_format_context, video_file_encoder_codec))) { TacticalAbort(); return; } AVCodecContext * video_file_codec_context = video_file_stream->codec; // MARKER TWO // error -22/-21 in avio_open2 if this is skipped if ((errorNum = avcodec_copy_context(video_file_codec_context, rtsp_vidstream_codec_context)) != 0) { TacticalAbort(); throw std::exception("avcodec_copy_context"); } //video_file_codec_context->codec_tag = 0; /* // MARKER 3 - is this not needed? Examples suggest not. if ((errorNum = avcodec_open2(video_file_codec_context, video_file_encoder_codec, &opts)) < 0) { errOut << "Couldn't open video file codec context: avcodec_open2 failed with error " << errorNum << ": " << ErrorRead(errorNum); std::string log = errOut.str(); TacticalAbort(); throw std::exception("avcodec_open2, video file"); }*/ //video_file_format_context->flags |= AVFMT_FLAG_GENPTS; if (video_file_format_context->oformat->flags & AVFMT_GLOBALHEADER) { video_file_codec_context->flags |= CODEC_FLAG_GLOBAL_HEADER; } if ((errorNum = avformat_write_header(video_file_format_context, &opts)) < 0) { errOut << "Couldn't open video file: avformat_write_header failed with error " << errorNum << ":\r\n" << ErrorRead(errorNum); std::string log = errOut.str(); TacticalAbort(); return; }
However, there are several issues:
- I can't pass any x264 options to the output file. The output H264 matches the input H264's profile/level - switching cameras to a different model switches H264 level.
- The timing of the output file is off, noticeably.
- The duration of the output file is off, massively. A few seconds of footage becomes hours, although playtime doesn't match. (FWIW, I'm using VLC to play them.)
Passing x264 options
If I manually increment PTS per packet, and set DTS equal to PTS, it plays too fast, ~2-3 seconds' worth of footage in one second playtime, and duration is hours long. The footage also blurs past several seconds, about 10 seconds' footage in a second.
If I let FFMPEG decide (with or without GENPTS flag), the file has a variable frame rate (probably as expected), but it plays the whole file in an instant and has a long duration too (over forty hours for a few seconds). The duration isn't "real", as the file plays in an instant.
At Marker One, I try to set the profile by passing options to
avio_open2
. The options are simply ignored by libx264. I've tried:av_dict_set(&opts, "vprofile", "main", 0); av_dict_set(&opts, "profile", "main", 0); // error, missing '(' // FF_PROFILE_H264_MAIN equals 77, so I also tried av_dict_set(&opts, "vprofile", "77", 0); av_dict_set(&opts, "profile", "77", 0);
It does seem to read the profile setting, but it doesn't use them. At Marker Two, I tried to set it after the
avio_open2
, beforeavformat_write_header
.// I tried all 4 av_dict_set from earlier, passing it to avformat_write_header. // None had any effect, they weren't consumed. av_opt_set(video_file_codec_context, "profile", "77", 0); av_opt_set(video_file_codec_context, "profile", "main", 0); video_file_codec_context->profile = FF_PROFILE_H264_MAIN; av_opt_set(video_file_codec_context->priv_data, "profile", "77", 0); av_opt_set(video_file_codec_context->priv_data, "profile", "main", 0);
Messing with privdata made the program unstable, but I was trying anything at that point. I'd like to solve issue 1 with passing settings, since I imagine it'd bottleneck any attempt to solve issues 2 or 3.
I've been fiddling with this for the better part of a month now. I've been through dozens of documentation, Q&As, examples. It doesn't help that quite a few are outdated.
Any help would be appreciated.
Cheers
-
BGRA to YUV420 FFmpeg giving bad output
6 octobre 2020, par NewbieCoderMy purpose is a screen recorder. I am using the Windows DXGI API to receive screenshots and I'm encoding the screenshots into a video using libx264. Feeding BGRA images directly to libx264 is producing weird colors in the output video. So, to get correct colors, I am trying to convert the BGRA to YUV420p. To speed up encoding, I am also trying to downscale the BGRA image.
So I am getting an 1920x1080 BGRA image and I want to convert it to 1280x720 YUV420p. For this, I am using FFmpeg swscale library to do both the format conversion and downscaling.
The problem is that the output video is coming like 3 images in the same frame. Please see this video. https://imgur.com/a/EYimjrJ
I tried just BGRA to YUV conversion without any downscaling and it is working fine. But BGRA to YUV with downscaling is giving this problem.
What is the cause for this problem? How do I fix it?
Here is my code snippet:
uint8_t* Image; x264_picture_t picIn, picOut; x264_picture_alloc(&picIn, X264_CSP_I420, 1280, 720); SwsContext* sws = sws_getContext(1920, 1080, AV_PIX_FMT_BGRA, 1280, 720, AV_PIX_FMT_YUV420P, SWS_BILINEAR, NULL, NULL, NULL); while (true) { take_screenshot(&Image); AVFrame BGRA; BGRA.linesize[0] = 1280 * 4; BGRA.data[0] = Image; sws_scale(sws, BGRA.data, BGRA.linesize, 0, 1080, picIn.img.plane, picIn.img.i_stride); nal_size = x264_encoder_encode(h, &nals, &nal_count, &picIn, &picOut); save_to_flv(nals, nal_size, nal_count); }
Here are my libx264 parameters:
x264_param_default_preset(¶m, preset, 0); param.i_csp = X264_CSP_I420; param.i_width = 1280; param.i_height = 720; param.i_fps_num = 30; param.i_fps_den = 1; param.rc.i_bitrate = 2500; param.i_bframe = 0; param.b_repeat_headers = 0; param.b_annexb = 1; x264_param_apply_profile(¶m, 0); h = x264_encoder_open(¶m);
-
FFmpeg : Segment muxer does not work for AVC-MXF
5 octobre 2020, par Mitra MI'm trying to save input stream to separate files every 60 seconds with the following command:
ffmpeg -i Input -vcodec libx264 -s 1920x1080 -pix_fmt yuv422p10le -aspect 16:9 -acodec pcm_s24le -ac 2 -ar 48000 -f segment -strftime 1 -segment_time 60 -y "e://o1/%H-%M-%S.mxf"
but getting this errors:
[mxf @ 000002111453c640] h264 profile not supported0:00.62 bitrate=N/A speed=1.23x [mxf @ 000002111453c640] could not get h264 profile av_interleaved_write_frame(): Operation not permitted
Note: The following 3 commands work without any errors:
1- ffmpeg -i Input -vcodec libx264 -s 1920x1080 -pix_fmt yuv422p10le -aspect 16:9 -acodec pcm_s24le -ac 2 -ar 48000 -f segment -strftime 1 -segment_time 60 -y "e://o1/%H-%M-%S.ts" 2- ffmpeg -i Input -vcodec libx264 -s 1920x1080 -pix_fmt yuv422p10le -aspect 16:9 -acodec pcm_s24le -ac 2 -ar 48000 -f mxf -f segment -strftime 1 -segment_time 60 -y "e://o1/%H-%M-%S.mkv" 3- ffmpeg -i Input -vcodec libx264 -s 1920x1080 -pix_fmt yuv422p10le -aspect 16:9 -acodec pcm_s24le -ac 2 -ar 48000 out.mxf"
(I think a private option of encoder not used for segments but I don't know how to find it.)
Q : How to save input live stream to separate mxf files every 60 seconds? (using AVC codec + MXF format)
-
ffmpeg - libx264 + slideshow produces smeared output [duplicate]
22 septembre 2020, par epilitimusI recently upgraded to ffmpeg version 4.3.1 with libx264.
When I use it to generate a single image slideshow
ffmpeg -y -loop 1 -i shapes.jpg -t 0:0:5 -vcodec libx264 output.mp4
I get a smeared image that looks like a technicolor waterfall (I know the -vcodec is redundant here).If I force use of the mpeg4 codec
ffmpeg -y -loop 1 -i shapes.jpg -t 0:0:5 -vcodec mpeg4 output.mp4
everything works fine.
I have tried several different input images but for example: https://cdn4.vectorstock.com/i/1000x1000/84/48/simple-geometric-shape-vector-13698448.jpg
produces this: technicolor waterfall
I think this is a bug but I just want to check and make sure I'm not doing something DUH! worthy before I report it.
I can use the libx264 codec for other things like converting formats and it works fine. I only see this when converting an image to a video.