Newest 'ffmpeg' Questions - Stack Overflow
Les articles publiés sur le site
-
Random audio/video sync issue with libcamera-vid + ffmpeg on raspberry pi 3a+
8 mai, par kepperiI have been working on camera software, which will stream live fullhd video to Cloudflare Stream via RTMPS protocol. Everything is mostly working nicely, but I have occasional A/V sync issues with the streams: Stream might start with correct A/V sync and it will stay correct until the end (1-2 h stream), but sometimes the A/V sync is misaligned like 1-2 sec so, that the audio is either behind or ahead of the video stream. And it will be like that until the end of the stream, then next stream might be just fine.
I'm using libcamera-vid for the video and ffmpeg for the audio, muxing and sending all to Cloudflare. This is my command:
libcamera-vid --width 1920 --height 1080 --framerate 30 --timeout 0 --nopreview true --inline 1 --codec h264 --verbose 0 --intra 90 --bitrate 4000000 --output - | ffmpeg -use_wallclock_as_timestamps 1 -loglevel error -probesize 10M -analyzeduration 5M -fflags +genpts -thread_queue_size 512 -f h264 -framerate 30 -i - -thread_queue_size 8192 -itsoffset 0.7 -f alsa -channels 1 -ar 44100 -i hw:1,0 -c:v copy -c:a aac -b:a 96000 -fflags +genpts -async 1 -shortest -f flv - | ( sleep 5; ffmpeg -re -i - -c copy -f flv "rtmps://live.cloudflare.com:443/live/..."
So I can control initial A/V sync with -itsoffset and it is working, but still I encounter those random sync differences.
I have also added the second ffmpeg command with 5 sec sleep to give the first ffmpeg process enough time to align with video and audio input before sending them to Cloudflare, but this seems not helping.
I have also tried with Gstreamer, which fixed the AV issue completely, but it had weird glitches on video frames if the audio was enabled. Seemed like it tried to match the audio and video timestamps on fly and that caused warps/jumps and ghost frames on video. Audio was just fine.
Here is my Gstreamer command (which will also have the same libcamera-vid piped in via fdsrc)
GST_CLOCK_SYSTEM=1 gst-launch-1.0 -v fdsrc blocksize=524288 ! h264parse config-interval=1 disable-passthrough=true ! queue max-size-buffers=200 max-size-time=4000000000 max-size-bytes=0 ! flvmux name=mux streamable=true latency=200 ! queue max-size-buffers=200 max-size-time=4000000000 max-size-bytes=0 ! rtmpsink sync=false location="rtmps://live.cloudflare.com:443/live/..." alsasrc device=hw:1,0 buffer-time=1000000 latency-time=200000 ! audio/x-raw,rate=44100,channels=1,format=S16LE ! queue leaky=downstream max-size-buffers=500 max-size-time=15000000000 max-size-bytes=0 ! audioconvert ! audioresample ! avenc_aac bitrate=96000 ! aacparse ! queue max-size-buffers=100 max-size-time=4000000000 max-size-bytes=0 ! mux.
With Gstreamer, I have been experimenting different sizes of buffers, but no luck getting rid of the video glitches. If I remove audio from that gst-launch-1.0 command, video is just perfect.
Hardware:
- RPI 3A+ (tested also with RPI4)
- RPI HQ M12 camera module
- Cheap USB tiny mic (like this: https://www.digikey.fi/fi/products/detail/seeed-technology-co-ltd/114992002/10451894)
I have also tried MUX instead of Cloudflare Stream, both acts identically so I guess the problem is not in receiving end encoding. This is also the reason I have not yet tried to "stream" into file.
Currently I'm in a process of testing the libcamera-vid with raw yuv420 + ffmpeg but with ffmpeg encoding the video instead of just having encoded h264 from libcamera-vid. This is done with RPI4 since it has enough CPU for it.
All help is appreciated!
-
ffmpeg, stretch audio to x seconds
8 mai, par Max DoumitI am trying to make an audio file be exactly x second.
So far i tried using the
atempo
filter by doing the following calculationAudio length / desired length = atempo.
But this is not accurate, and I am having to tweak the tempo manually to get it to an exact fit.
Are there any other solutions to get this work ? Or am I doing this incorrectly?
My original file is a wav file, and my output in an mp3
Here is a sample command
ffmpeg -i input.wav -codec:a libmp3lame -filter:a "atempo=0.9992323" -b:a 320K output.mp3
UPDATE:
I was able to correctly calculate the tempo by changing the way I am receiving the audio length.
I am now calculating the current audio length using the actual file size and the sample rate.
Audio Length = file size / (sample rate * 2)
Sample rate is something like 16000 Hz. You can get that by using ffprob or ffmpeg.
-
Major quality loss when encoding with ffmpeg [closed]
6 mai, par Player_X_YTI am trying to edit videos in davinci resolve. It has limitations on what encoding I can import in the free version. I am trying to get around this by re-encoding the video file with ffmpeg. The following command is used to isolate the video track and encode it with mpeg-4:
ffmpeg -y -i "$1" -an -vcodec mpeg4 "$1-VIDEO.mp4"
However there is a significant loss in quality. I tried to force lossless quality but it doesn't change anything:
ffmpeg -y -i "$1" -an -crf 0 -vcodec mpeg4 "$1-VIDEO.mp4"
The video when rendered looks like it would when the bitrate drops, as in the pixels show up during motion. But dolphin states that the bitrate is actually higher than the source
2.6M -> 3.01M
why do the videos continue to look like this? -
cmake installation of x265 for ffmpeg on Cygwin - executable location different from other codecs
6 mai, par bballdave025TL;DR (with expected vs. real)
For a Cygwin build of
ffmpeg
, I'm installingx265
, and it seems to me that the executable ends up in the wrong place. I'll show some basic directory structure, then I'll show thetree
outputs for expected and real, both before and after thecmake
installation. For directories where I think this is important, I'll show the outputs before and after thecmake
installation.My question has two parts. I used the following
cmake
andmake
commands,# pwd => $HOME/programs/ffmpeg/ffmpeg_sources/x265/build/linux PATH="$HOME/programs/ffmpeg/bin:$PATH" \ cmake -G "Unix Makefiles" \ -DCMAKE_INSTALL_PREFIX="$HOME/programs/ffmpeg/ffmpeg_build" \ -DENABLE_SHARED=OFF \ -DCMAKE_EXE_LINKER_FLAGS="-static" ../../source PATH="$HOME/programs/ffmpeg/bin:$PATH" make -j $(nproc) make install
The result is below, with my real vs. expected, and there is a more detailed, more explicit, and hopefully more clear file with the info.
at pastebin.com/86wHrtxR.Edit: I've made a copy of the detailed/explicit/clear file on my GitHub as a gist. This should be more secure. (The Pastebin version still exists, in case that is your preference.)
Now, for my two-part question:
How can I change my
cmake
command so that myx265.exe
file ends up in$HOME/programs/ffmpeg/bin
with the proper linking, rather than$HOME/programs/ffmpeg/ffmpeg_build/bin
?Would the build/linker/whatever figure things out for the
ffmpeg
build?
I want to know the answer to question number 1 regardless of the answer to question number 2. I haven't used
cmake
with the-DVAR=var
flags before, and I'd like to take this opportunity to learn.For the result:
Things surrounded by double curly brackets are
{{ expected }}
.Things surrounded by double angle brackets are
<< real >>
, i.e. they exist after the installation is done.If real matches expected, and the file/directory is new, I've surrounded it by double parentheses, i.e. double round brackets.
(( match ))
If something is not new (and thus has the same before and after) I haven't marked it.
me@MACHINE ~/programs/ffmpeg $ tree --charset=ascii bin bin |-- lame.exe |-- mp3rtp.exe |-- mp3x.exe `-- x264.exe {{ `-- x265.exe }} ## Expected, not Exists me@MACHINE ~/programs/ffmpeg $ tree --charset=ascii \ ffmpeg_build ffmpeg_build << |-- bin >> ## Not expected, Exists << | `-- x265.exe >> ## Not expected, Exists |-- include | |-- fdk-aac | | |-- aacdecoder_lib.h | | |-- aacenc_lib.h | | `-- ...
| |-- lame | | `-- lame.h | |-- x264.h | `-- x264_config.h (( | |-- x265.h )) ## Expected and Exists (( | `-- x265_config.h )) ## Expected and Exists |-- lib | |-- libfdk-aac.a | |-- libfdk-aac.la | |-- libmp3lame.a | |-- libmp3lame.la (( | |-- libx265.a )) ## Expected and Exists | `-- pkgconfig | |-- fdk-aac.pc | `-- x264.pc (( | `-- x265.pc )) ## Expected and Exists `-- share |-- doc | ... `-- man ... Other, possibly useful information about the build directory structure.
me@MACHINE ~/programs/ffmpeg $ tree --charset=ascii -L 1 . . |-- bin |-- ffmpeg_build `-- ffmpeg_sources 3 directories, 0 files
For this next,
ffmpeg_sources
dir, I'm showing the after (which is both expected and real/exists) surrounded by double parentheses, i.e. double round brackets,((
.)) me@MACHINE ~/programs/ffmpeg $ tree --charset=ascii -L 1 ffmpeg_sources ffmpeg_sources |-- fdk-aac.zip |-- lame-svn |-- mstorsjo-fdk-aac-e7d8591 |-- x264-snapshot-20191217-2245 |-- x264-snapshot-20191217-2245.tar.bz2 `-- x264-snapshot-20191218-README.txt (( `-- x265 )) 3 directories, 3 files (( 4 directories, 3 files ))
NOW, FOR SOME MORE DETAIL
What I'm Doing
I am working on a Cygwin build (vs. a Windows/mingw build) of
ffmpeg
. I am following an older guide by koohiimaster (archived). That guide says,[W]e are not cross-compiling for windows; we are compiling for Cygwin.
This 2014 guide doesn't have all of the codecs I want - I want as complete a build as possible - so I've also been referring to this ffmpeg-for-Ubuntu guide (archived), which I hope is kept up-to-date. It's referred to by koohiimaster.
Also, as a way of checking that I'm getting all the codecs I want, I've been looking at this FFmpeg for Windows guide from SuperUser
I'll give the basics of my steps below.
More details, as well as all the output is at pastebin.com/suL1nU6Z.Edit: I've put the log of terminal input/output for all my steps into a gist at my GitHub as this seems safer than Pastebin.
A look at directory structure for the build
me@MACHINE ~/programs/ffmpeg $ cd $HOME/programs/ffmpeg me@MACHINE ~/programs/ffmpeg $ tree --charset=ascii -d -L 1 . |-- bin |-- ffmpeg_build `-- ffmpeg_sources 3 directories
Getting the source. Note that I had to
apt-cyg install mercurial
, though (with my Cygwin setup GUI/EXE in my Cygwin root directory, i.e.C:\cygwin64\setup-x86_64.exe
), I could also have done/setup-x86_64.exe install -q -P mercurial
.cd ffmpeg_sources hg clone https://bitbucket.org/multicoreware/x265
Running the
cmake
andmake
commandscd x265/build/linux PATH="$HOME/programs/ffmpeg/bin:$PATH" \ cmake -G "Unix Makefiles" \ -DCMAKE_INSTALL_PREFIX="$HOME/programs/ffmpeg/ffmpeg_build" \ -DENABLE_SHARED=OFF \ -DCMAKE_EXE_LINKER_FLAGS="-static" \ ../../source PATH="$HOME/programs/ffmpeg/bin:$PATH" make -j $(nproc) make install
It was the last part (actually the very last line) of the
make install
output that worried me. Here is the whole output - it's not very long.make[1]: Entering directory '/home/me/programs/ffmpeg/ffmpeg_sources/x265/build/linux' make[2]: Entering directory '/home/me/programs/ffmpeg/ffmpeg_sources/x265/build/linux' make[2]: Leaving directory '/home/me/programs/ffmpeg/ffmpeg_sources/x265/build/linux' [ 20%] Built target encoder make[2]: Entering directory '/home/me/programs/ffmpeg/ffmpeg_sources/x265/build/linux' make[2]: Leaving directory '/home/me/programs/ffmpeg/ffmpeg_sources/x265/build/linux' [ 83%] Built target common make[2]: Entering directory '/home/me/programs/ffmpeg/ffmpeg_sources/x265/build/linux' make[2]: Leaving directory '/home/me/programs/ffmpeg/ffmpeg_sources/x265/build/linux' [ 84%] Built target x265-static make[2]: Entering directory '/home/me/programs/ffmpeg/ffmpeg_sources/x265/build/linux' make[2]: Leaving directory '/home/me/programs/ffmpeg/ffmpeg_sources/x265/build/linux' [100%] Built target cli make[1]: Leaving directory '/home/me/programs/ffmpeg/ffmpeg_sources/x265/build/linux' Install the project... -- Install configuration: "Release" -- Installing: /home/me/programs/ffmpeg/ffmpeg_build/lib/libx265.a -- Installing: /home/me/programs/ffmpeg/ffmpeg_build/include/x265.h -- Installing: /home/me/programs/ffmpeg/ffmpeg_build/include/x265_config.h -- Installing: /home/me/programs/ffmpeg/ffmpeg_build/lib/pkgconfig/x265.pc -- Installing: /home/me/programs/ffmpeg/ffmpeg_build/bin/x265.exe
As discussed in the TL;DR section, I expected to see
x265.exe
athome/me/programs/ffmpeg/bin/x265.exe
rather than the path given on the last line of output,
/home/me/programs/ffmpeg/ffmpeg_build/bin/x265.exe
This worries me especially because the first part of the
ffmpeg
install command that my instructions inform me to run isPATH="$HOME/programs/ffmpeg/bin:$PATH" \ PKG_CONFIG_PATH="$HOME/programs/ffmpeg/ffmpeg_build/lib/pkgconfig" \ ./configure \ --prefix="$HOME/programs/ffmpeg/ffmpeg_build" \ --extra-cflags="-I$HOME/programs/ffmpeg/ffmpeg_build/include" \ --extra-ldflags="-L$HOME/programs/ffmpeg/ffmpeg_build/lib" \ --bindir="$HOME/programs/ffmpeg/bin" \
... and on it goes ...
It would seem to me that the
.configure
script forffmpeg
won't find thex265
executable, since it's not in thebindir
.I'll repeat my two-part question from before:
- How can I change my
cmake
command so that myx265.exe
file ends up in$HOME/programs/ffmpeg/bin
with the proper linking, rather than$HOME/programs/ffmpeg/ffmpeg_build/bin
?
What I'm looking for here is something akin to the
--bindir
flag frommake
's./confiure
.- Would the build/linker/whatever figure things out for the
ffmpeg
build?
I want to know the answer to question number 1 regardless of the answer to question number 2. I haven't used
cmake
with the-DVAR=var
flags before, and I'd like to take this opportunity to learn.
Where I've Looked & What I've Tried
I first started with the
man
page and the--help
forcmake
. That was scary. I was hoping that I'd find something useful around theCMAKE_INSTALL_PREFIX
stuff, but I wasn't sure what to make of it.I tried
grep
ing throughcmake --help-full
(with 50 lines before and after whatever I was searching for), but got tripped up by the complexity. I've only used basiccmake
stuff, before, and I got more than a little lost.Even with the
--help
, I don't know if I need to look at thehelp-manual
, thehelp-command
, thehelp-module
, thehelp-policy
, thehelp-variable
, or something else.It seemed to me, in reading, that a "binary directory" is the top of the "build", whereas I thought it would be the dir named
bin
... I couldn't tell what things were meant to be used by the person creating the package rather than by me, who am trying to make/build the package from the command line.I looked through what seemed to be a
cmake
wiki's Useful Variables page (archived), as well as at this thread at cmake.org (archived), which, along with this SO source and this and this and this and this SO sources, seemed to suggest using theCMAKE_RUNTIME_OUTPUT_DIRECTORY
variable (since theEXECUTABLE_OUTPUT-DIRECTORY
variable has been superseded by it). By the way, I couldn't tell which things should be used by the creator of the package vs. the consumer of the package - the consumer being me. I tried withPATH="$HOME/programs/ffmpeg/bin:$PATH" \ cmake -G "Unix Makefiles" \ -DCMAKE_INSTALL_PREFIX="$HOME/programs/ffmpeg/ffmpeg_build" \ -DCMAKE_RUNTIME_OUTPUT_DIRECTORY="$HOME/programs/ffmpeg/bin" \ -DENABLE_SHARED=OFF \ -DCMAKE_EXE_LINKER_FLAGS="-static" ../../source PATH="$HOME/
and have thought about fifty-or-so other -DVAR variables, but with any I have tried, I still get the same result. I still get the executable in what seems to be the wrong place.
System Details
$ date && date +'%s' Tue, May 5, 2020 11:14:40 AM 1588698880 $ uname -a CYGWIN_NT-10.0 MACHINE 3.1.4(0.340/5/3) 2020-02-19 08:49 x86_64 Cygwin $ cmake --version cmake version 3.14.5 CMake suite maintained and supported by Kitware (kitware.com/cmake). $ bash --version | head -n 1 GNU bash, version 4.4.12(3)-release (x86_64-unknown-cygwin) $ gcc --version | head -n 1 gcc (GCC) 9.3.0 $ g++ --version | head -n 1 g++ (GCC) 9.3.0 $ make --version | head -n 2 GNU Make 4.3 Built for x86_64-pc-cygwin
-
Button "Clean FFMeta" does nothing after compiling with PyInstaller
6 mai, par Leonie HoldermannI’m working on my first Python project and I’ve compiled it into an executable using PyInstaller with the following command:
pyinstaller --onefile --noconsole app.py
However, when I run the executable, the button "Clean FFMeta" which triggers the clean_ffmeta() function does nothing. Additionally, changing the language or the chapter settings under the "Options -> Chapter settings" menu doesn’t seem to affect anything either. It all works perfectly in the Python script before compilation, but once compiled into an .exe, none of these functions respond.
I've reviewed the code, and the button is correctly linked to the function, but I suspect something might be going wrong during the compilation process.
What I have tried:
- Checked that all dependencies are included.
- Verified that the configuration and language changes are being correctly applied before compilation.
- Tried running the executable from a console to check for error messages, but there are none visible (since I used --noconsole).
What I expect:
- The "Clean FFMeta" button should clean the FFMeta file based on the user settings.
- Language and chapter settings should be updated and reflected in the GUI immediately.
Code: Below is a simplified version of my code, especially the sections related to the "Clean FFMeta" functionality and language/chapter settings.
def clean_ffmeta(): if not config.get("cd_in_path"): show_error(texts[current_language]["error"] + " No CD_IN path configured.") return chapter_path = os.path.join(config["cd_in_path"], "chapters.ffmeta") cleaned_chapter_path = os.path.join(config["cd_in_path"], "chapters_cleaned.ffmeta") if not os.path.exists(chapter_path): show_error(texts[current_language]["no_chapters_file"]) return write_to_console("Starting to clean FFMeta...") thread = threading.Thread(target=clean_ffmeta_thread, args=(chapter_path, cleaned_chapter_path)) thread.start() def clean_ffmeta_thread(chapter_path, cleaned_chapter_path): try: chapter_action = config.get("chapter_action", "clean") keep_empty = config.get("chapter_keep_empty", False) write_to_console(f"Chapter action: {chapter_action}, Keep empty: {keep_empty}") with open(chapter_path, "r", encoding="utf-8") as f: lines = f.readlines() new_lines = [] chapter_counter = 0 for line in lines: stripped_line = line.strip() if stripped_line.startswith("title="): title_content = stripped_line[6:] if chapter_action == "clean": if title_content == "": if keep_empty: new_lines.append(line) else: write_to_console("Empty title skipped.") continue else: new_lines.append(line) elif chapter_action == "number": chapter_counter += 1 chapter_title = f"{texts[current_language]['chapter']} {chapter_counter}" new_lines.append(f"title={chapter_title}\n") write_to_console(f"Renamed to: {chapter_title}") else: new_lines.append(line) with open(cleaned_chapter_path, "w", encoding="utf-8") as f: f.writelines(new_lines) write_to_console(f"FFMeta cleaned and saved as '{cleaned_chapter_path}'.") except Exception as e: write_to_console(f"Error cleaning FFMeta: {str(e)}") def open_chapter_settings(): global chapter_settings_window, chapter_action_var global chapter_keep_empty_checkbox, chapter_save_button chapter_settings_window = tk.Toplevel(root) chapter_settings_window.title(texts[current_language]["chapter_setting_title"]) chapter_settings_window.geometry("300x250") chapter_settings_window.resizable(False, False) chapter_action_var = tk.StringVar(value=config.get("chapter_action", "clean")) chapter_keep_empty_var = tk.BooleanVar(value=config.get("chapter_keep_empty", False)) tk.Label( chapter_settings_window, text=texts[current_language]["chapter_setting_choose_option"] ).pack(pady=(10, 5)) tk.Radiobutton( chapter_settings_window, text=texts[current_language]["chapter_setting_clean"], variable=chapter_action_var, value="clean" ).pack(pady=5) tk.Radiobutton( chapter_settings_window, text=texts[current_language]["chapter_setting_number"], variable=chapter_action_var, value="number" ).pack(pady=5) chapter_keep_empty_checkbox = tk.Checkbutton( chapter_settings_window, text=texts[current_language]["chapter_setting_keep_empty"], variable=chapter_keep_empty_var ) chapter_keep_empty_checkbox.pack(pady=5) chapter_save_button = tk.Button( chapter_settings_window, text=texts[current_language]["chapter_setting_save"], command=lambda: save_chapter_settings(chapter_keep_empty_var, chapter_settings_window) ) chapter_save_button.pack(pady=10) def save_chapter_settings(keep_empty_var, window): config["chapter_action"] = chapter_action_var.get() config["chapter_keep_empty"] = keep_empty_var.get() save_config() write_to_console(f"Chapter settings saved: Action={config['chapter_action']}, Keep empty={config['chapter_keep_empty']}") window.destroy() options_menu = tk.Menu(menu, tearoff=0) options_menu.add_command(label="Check pip-ffmpeg", command=check_pip_ffmpeg) options_menu.add_command(label=texts[current_language]["menu_chapter_settings"], command=open_chapter_settings) menu.add_cascade(label="Options", menu=options_menu) btn3 = tk.Button(btn_frame, text="3. Clean FFMeta", command=clean_ffmeta) btn3.grid(row=0, column=2, padx=5)
Here you find the entire project code of the entire project: https://www.pythonmorsels.com/p/32hkh/
Why is the clean_chapters function not working?