anthwlock / untrunc

Restore a truncated mp4/mov. Improved version of ponchio/untrunc
GNU General Public License v2.0
1.9k stars 182 forks source link

Compile statically? #32

Closed sammarks closed 4 years ago

sammarks commented 4 years ago

Are there any configuration preferences for the makefile to compile this statically?

anthwlock commented 4 years ago

What system? Why do you want a static build? Anyway, this will link statically.

sammarks commented 4 years ago

I'm building it to run inside AWS Lambda, so unfortunately can't install all of the required shared libraries inside their execution environment before running this.

That's the build step I'm using at the moment, and am running into this error when executing inside Lambda:

error while loading shared libraries: libbz2.so.1.0: cannot open shared object file: No such file or directory

For more context, to make sure I'm understanding the required process here. Lambda runs inside AWS Linux, so all I should need to do is just compile this library statically inside an AWS Linux Docker container and then send up the binary with my code where I should be able to execute it without issue.

After reading through the Makefile, I think I see where you're linking the ffmpeg dependencies statically if you use a specific version (I'm using the version mentioned in the README). But I'm stuck when it comes to linking the rest of the dependencies statically.

I tried adding -static to the end of this line, but that ended up throwing errors at compile time about X11 dependencies. Here's a chunk of those errors:

ffmpeg-3.3.9/libavcodec/libavcodec.a(cuvid.o): In function `cuvid_load_functions':
/untrunc-master/ffmpeg-3.3.9/./compat/cuda/dynlink_loader.h:202: warning: Using 'dlopen' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
ffmpeg-3.3.9/libavformat/libavformat.a(rtsp.o): In function `get_sockaddr':
/untrunc-master/ffmpeg-3.3.9/libavformat/rtsp.c:194: warning: Using 'getaddrinfo' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
/usr/lib/gcc/x86_64-linux-gnu/4.9/../../../x86_64-linux-gnu/libX11.a(ClDisplay.o): In function `XCloseDisplay':
(.text+0xd3): undefined reference to `xcb_disconnect'
/usr/lib/gcc/x86_64-linux-gnu/4.9/../../../x86_64-linux-gnu/libX11.a(OpenDis.o): In function `OutOfMemory':
(.text+0x484): undefined reference to `xcb_disconnect'
/usr/lib/gcc/x86_64-linux-gnu/4.9/../../../x86_64-linux-gnu/libX11.a(OpenDis.o): In function `XOpenDisplay':
(.text+0x8bb): undefined reference to `xcb_get_setup'

And here is the change I made to the makefile to result in the compile-time errors.

anthwlock commented 4 years ago

Hmm.. finding the missing library can be quite cumbersome..

What about writing a little script which copies every shared library which untrunc needs to your deploy folder? That's what I did for the windows builds. Instead of depends you could use ldd.

You should probably filter ldd's output though, as libraries like libc should alredy exist..

I am curious.. why would someone need untrunc on aws lambda? Do you have tons of broken videos? Or plan some sort of service, where broken recordings need to automatically be recovered? I never used AWS lambda..

sammarks commented 4 years ago

Thanks for the info! I'll try and modify that and see where I end up.

I have a bunch of MP4 fragments (basically just chunks of a bigger MP4 file, split apart and uploaded to S3 individually), and the Lambda concatenates all of them together very simply, and then runs the final result through untrunc to restore the required metadata, timecodes, etc to get a playable MP4 file.

And mostly just using Lambda as opposed to a Docker container for pricing reasons. Much cheaper to run it this way since I only have to pay for the seconds that I use.

sammarks commented 4 years ago

That did the trick! I ended up having to go back to the original fork of the project - it worked for the particular videos I'm uploading, and the new fork throws errors about multiple frames in the same packet (looks like it's coming from AAC).

For reference, here are the relevant lines on the Dockerfile:

RUN mkdir /untrunc-dist && cp untrunc /untrunc-dist
WORKDIR /untrunc-dist
RUN ldd untrunc | grep -Po "(?<= \=\> )[^(]+(?=\(0x)" > depfiles.txt
RUN bash -c 'while read -r line; do cp -v $line ./; done <<<$(cat depfiles.txt); exit 0'

# Remove unnecessary untrunc shared libraries for Amazon Linux.
RUN rm -v depfiles.txt libc.so.6 libgcc_s.so.1 libm.so.6 libpthread.so.0 libstdc++.so.6 libz.so.1

I also modified the Dockerfile to do the building inside an Amazon Linux box instead of Ubuntu (so had to change the apt-get calls to their yum equivalents).

Then just modified my code to package that up with the Lambda, and used LD_LIBRARY_PATH whenever running untrunc inside the Lambda.

anthwlock commented 4 years ago

Great!

The [aac @ 0x55e00a329300] Multiple frames in a packet. shouldn't be a problem though. It is handled and explained here:

// ffmpeg 3.4+ uses internal buffer which needs to be updated. // this is slow because of the internal memory allocation. // ff34+ decodes till exhaustion, which in turn spams repetitive warnings/errors

It should output the following directly after the 'Multiple frames' message:

Info: Muted ffmpeg to reduce redundant warnings/errors. Use '-v' to see them.

If you don't mind create a new issue, with the full output combined with untrunc -i <ok.mp4>.

FYI, the original untrunc loads the whole file into RAM, which can be quite a problem..

sammarks commented 4 years ago

I start working on this again on Thursday of this week - I will get that output for you then and post it back here.

anthwlock commented 4 years ago

apparently not. :)