How to fix a broken MP4/MOV video (ffmpeg reports "moov atom not found")

Let's assume your video recorder (phone, camera, etc.) died while recording an MP4 (or MOV or 3GP ... they are mostly the same container format). If you try to read/analyze it with ffmpeg, it'll tell you that "moov atom not found". The problem is that recorders put the most important part of the video (this so called moov atom) at the end of the video file. It contains the index of the video and the metadata (like codec, etc.). So everything that a video player needs to know to be able to play it back. The reason for this is simple: while you're recording the video, you don't have the full index yet. You only have it, when the recording is finished. And you don't know in advance how long the video is going to be so you cannot simply reserve some space for the index at the start of the recording.

There're tools that let you move the moov atom from the end of the file to the start so internet connected players can start playback instantly when they start downloading the file (instead of having to wait til the entire file is downloaded). However this won't help you if your moov is missing altogether.

It'd seem that this problem is more widespread and there're lots of apps that can help you fix such broken files. Unfortunately that's not the case. Actually I've found only a single app called Grau's Video Repair Tool. It's a bit costly for the average user, but you can buy the license for the repair of a limited number of videos significantly cheaper. However the tool's earlier versions were freeware and if you happen to find a copy online (direct link), you can still use it. Smile Obviously the tool has seen quite a few versions since then, so if the free version does not work, you can still try the current demo version and if it works, you can buy a license for recovery of 5 video files. (P.S.: the free version pretty much works for me ... at least with the broken videos created by my phone's camera app in case it crashes for some reason before the recording is finished)

P.S.: obviously the free version of Grau's Video Repair Tool is hard to come by these days. The official site has removed it long ago and various links to copies become invalid after some time. You should search for the filename that was originally used to publish it: "videorepair1.5.zip"

Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

fix mov file

Hi, Smile

Software mentioned in the above blog is quite promising, but i know one more software which i used, when i faced this problem. Few days before I was watching my favorite movie on my laptop but it stops in between while playing and starts giving error message. Later on when I met with my uncle I told this problem to him, he suggested me to use mov repair tool to fix mov movie file. I used this tool and got my movie file back. To know how click on the page links: http://www.movrepair.net/fix-mov-movie-file.html

Re: fix mov file

Thanks, I'll check it out. It's pretty easy to reproduce my problem, I can create a broken MP4 (one without a MOOV atom) anytime. Smile

Re: fix mov file

Well ... I did give it a go. But when it's first thing upon startup was to ask for my password to "make changes", I quit the app. There was no additional documentation in the downloaded DMG, so I couldn't check what exactly intended the app to do. I don't really think that to use the app I should give it administrative privileges on my Mac. Sorry, this one was a no go for me.

repair MOV file

This is very useful statement.but I found one tool “Remo repair Mov” on internet and it is quite good in repairing MOV file.

Re: repair MOV file

It's the same tool as suggested by aurthur.

It worked!

Grau's HD Video Repair Utility worked, and saved a corrupted video (.3gp from my Droid X) of my daughter getting on the school bus for the first time! Thank you so much!

Avoid the issue during recording.

Hi,

I had the same issue and found the best way is to have avconv/ffmpeg write the necessary header information right away during recording thus avoiding currupt files. This is done by the "-f ismv" flag, also consider adding "-movflags frag_keyframe". This way, if the recording is interrupted, the file will not be corrupt. Also if you need to stop the recording, send a SIGINT instead of SIGTERM (default signal). This is done by '-2' in the kill command, e.g. 'kill -2 <ffmpeg-pid>'.

Hope this helps!

Re: Avoid the issue during recording

Thanks for the tip. Although I started my post with "let's assume your video recorder (phone, camera, etc.) died while recording an MP4 ...", thus the file to be repaired was not recorded by ffmpeg and the issue cannot be always avoided (eg. battery gets drained, storage gets full, etc.).

Yes, obviously those flags

Yes, obviously those flags won't prevent your recorder vom dying. But it prevents that the partially recorded MP4s are corrupt, because the index/codec information is written for each fragment, thus avoiding the issue of broken MP4/MOV videos when the recorder dies Wink

Re: Yes, obviously those flags

I think we're still talking about two very different things. Your tip works if one uses avconv/ffmpeg to record a video. My problem came from using a phone's camera or a camcorder. How do you "put" ffmpeg into these? Shock Most probably you don't. If you got a hardware (with a firmware) that produces faulty MP4 files under certain circumstances, then you need a way to fix these files. And this is what my original post was about.

Untrunc

I guess if somebody has the right motivation (eg. the recording of his nuptial ceremony gets corrupted due to dead battery and missing moov atom), he finds a way. Wink This is what happened to Federico who eventually came up with an open source (free) solution to his problem. He published his code on his blog (and via github). It's something of a hack and his only goal was to fix the one video he needed to recover. But the basics are there. If somebody would pick up the work Federico started, an open source MP4/MOV fixer (a viable alternative to Grau's Video Repair Tool) could be born.

MP4 Video Repair (for Android) by Iwo Banas

There's a solution for Android devices: https://play.google.com/store/apps/details?id=com.iwobanas.videorepair
Based on it's description, it seems this one works on the same principle as Grau's Video Repair Tool. The app has in-app purchases so it might ask you to buy some licenses for full video repair, I haven't tested it.

Dropbox url is dead. I have

Dropbox url is dead. I have found another url:

http://nagasoft.cn/download/videorepair1.5.zip

This worked

I had a bad file that I desperately wanted to recover. audio m4a with no atom moov at the end.

Although the frequency is off, I was able to recover the audio otherwise using the steps here: http://sysfrontier.com/en/2014/12/31/hello-world/

Good luck to you.

Thank You for VideoRepair1.5.zip

I know this is an old article - but I had to say THANK YOU!

Had 3 .MDT files from a Panasonic LX100. Found this article and the "direct link" still worked.

Nothing short of miraculous the way Video Repair Tool 1.5 managed to recover all 3 .MDT files.

Thank you so much for posting this

Grau's still working, but with some snags...

So... seven years later, just like so many others, I came across your page as well, and attempted to fix a broken video... although I had no luck in my case, since your page is so often visited, I thought I'd add a few tips for 2019...

While the last few links to Grau's Video Repair Tool 1.5 are still working, there's a problem with using it under macOS Catalina (10.15): from Catalina onwards, only 64bit apps will run. Version 1.5 is way too old, so there is only the freeware version to work with.

To make matters worse, Grau seems to have abandoned all development (at least on the Mac side of things) around 2017 or so. Not all is lost, though; you'll be still able to get it working under macOS Catalina, so long as you are familiar with a Unix shell and have installed Brew or MacPorts or something similar (or, at least, the XCode compiler).

First, macOS Catalina is extremely cautious when running third-party apps from unknown developers (i.e. those who have no agreement with Apple for a valid digital signature to sign their own software with). Fortunately, Grau Online has a extremely detailed FAQ which explains how to authorise each component of the Video Repair tool so that you may run it freely.

Now, as far as I can see, Grau Online has developed its Video Repair tool with Embedded Lua. This means that they can develop once, and get it working on multiple platforms (Windows and macOS, in this case). However, their application is mostly a very sophisticated 'wrapper' around other common video processing tools with a GUI, namely, it calls ffmpeg, mencoder, and mplayer. Technically, only ffmpeg is really needed; mencoder will post-process and re-encode the repaired video so that it can be playable anywhere (this is an optional second step that can be selected and configured under the Options button). mplayer is a free and open-source multimedia player which runs from the command line and works pretty much with everything out there (useful if you can't watch the repaired video with the usual tools — QuickTime on the Mac, Media Player on Windows, etc.) Because most people won't have these tools installed, the developers have included a version of these tools as part of the ZIP file; the gs application (which is what you launch to get the Video Repair tool working) will only use those versions that come with the tool.

Unfortunately, though, these versions are from 2006 and 2011, which means that they're hopelessly outdated, and haven't been compiled to 64 bits (but they will still run under ancient hardware with PowerPC CPUs!).

The first thing to do, therefore, is to use either Brew or MacPorts to install the current versions of all these tools, then go to the folder where these are stored inside the videorepair folder (the ZIP file I've got had these files under videorepair/toolsdarwin/), rm them manually and add symbolic links to the new versions. If you're using Brew, these will be found under /usr/local/bin, so the commands you need to give under Terminal (assuming you've successfully downloaded all three of them) are:
cd {folder where you unpacked videorepair.zip... usually ~/Downloads}
cd videorepair/toolsdarwin/
rm ffmpeg mencoder mplayer
ln -s /usr/local/bin/ffmpeg
ln -s /usr/local/bin/mencoder
ln -s /usr/local/bin/mplayer
Now you can launch the video repair tool as explained under the instructions (basically, open the folder for videorepair and double-click on mac_start.command, then select the language to proceed), and all will work!

Well, not all — because this will be the 'freeware' version, it will only output half the movie, of course. Technically, though, you might be able to go to Options and select the last 50% of the movie, and theoretically, you'd get all the video — but I haven't tried it out, since, sadly, in my case, the recovery didn't work — although the logs from Video Repair show that the file contains a lot of video & audio information, once the file is 'repaired', it remains unplayable for some reason (VLC is able to play the audio... but there is no sound, either).

I'm now looking for alternatives (there are not many...) but, hopefully, my comment will help out those who wish to try the tool in macOS versions made from 2019 onwards, but has come across the errors coming from the provided 32-bit applications, which will be not only hopelessly outdated but also will not be able to run as macOS Catalina will refuse to run anything which is not specifically compiled 64-bits apps...

Re: Grau's still working, but with some snags...

Thanks for the detailed feedback and your experiences!

Found an open-source tool that worked for me - Untrunc

4-5 years ago my Mac died and I already decided which way I wanted to go: I switched to Ubuntu as my primary desktop OS for personal use (I've made this switch 10-15 years ago for work, but didn't want to ditch the Mac as long as it worked).

I've already envisioned an open-source solution to this specific problem (that Grau's Video Repair Tool solved for the most part) in a 2015's comment of this thread, but didn't look into it in detail.

It seems that the potential loss of a wedding ceremony video was motivation enough for a coder (Federico Ponchio) to actually write an open-sourced piece of code that does pretty much the same as Grau's tool. And voala: Untrunc was born! Smile
The repository is available here: https://github.com/ponchio/untrunc

This time I did test it by making two short videos with the same camera (a Samsung Galaxy S10 phone):
  • 20191025_141707.mp4
  • 20191025_141723.mp4
The latter was used as a "reference" (for a good video file) and the former was used (by cutting off it's end) as a "bad"/truncated video that has no moov atom.

Here's a short log of my test using Ubuntu 18:
my_user@my_desktop ~/temp % ls -al
total 28504
drwx------   2 my_user my_user     4096 okt   25 15:02 .
drwx------ 108 my_user my_user     4096 okt   25 15:02 ..
-rw-------   1 my_user my_user 19260358 okt   25 14:18 20191025_141707.mp4
-rw-------   1 my_user my_user  9914321 okt   25 14:18 20191025_141723.mp4

my_user@my_desktop ~/temp % AtomicParsley 20191025_141707.mp4 -T
Atom ftyp @ 0 of size: 24, ends @ 24
Atom mdat @ 24 of size: 19253489, ends @ 19253513
Atom moov @ 19253513 of size: 6845, ends @ 19260358
     Atom mvhd @ 19253521 of size: 108, ends @ 19253629
     Atom udta @ 19253629 of size: 66, ends @ 19253695
         Atom SDLN @ 19253637 of size: 16, ends @ 19253653                                         ~
(...)
                         Atom stts @ 19258162 of size: 32, ends @ 19258194
                         Atom stsz @ 19258194 of size: 2052, ends @ 19260246
                         Atom stsc @ 19260246 of size: 52, ends @ 19260298
                         Atom stco @ 19260298 of size: 60, ends @ 19260358

~ denotes an unknown atom
------------------------------------------------------
Total size: 19260358 bytes; 45 atoms total. AtomicParsley version: 0.9.0 (utf8)
Media data: 19253489 bytes; 6869 bytes all other atoms (0.036% atom overhead).
Total free atom space: 0 bytes; 0.000% waste.
------------------------------------------------------

my_user@my_desktop ~/temp % dd if=20191025_141707.mp4 bs=19252987 count=1 of=20191025_141707.no_moov.mp4
1+0 records in
1+0 records out
19252987 bytes (19 MB, 18 MiB) copied, 0,0178516 s, 1,1 GB/s

my_user@my_desktop ~/temp % AtomicParsley 20191025_141707.no_moov.mp4 -T
Atom ftyp @ 0 of size: 24, ends @ 24
Atom mdat @ 24 of size: 19252963, ends @ 19252987
------------------------------------------------------
Total size: 19252987 bytes; 1 atoms total. AtomicParsley version: 0.9.0 (utf8)
Media data: 19252963 bytes; 24 bytes all other atoms (0.000% atom overhead).
Total free atom space: 0 bytes; 0.000% waste.
------------------------------------------------------

my_user@my_desktop ~/temp % ffmpeg -i 20191025_141707.no_moov.mp4
ffmpeg version 4.2.1-0york0~18.04.1 Copyright (c) 2000-2019 the FFmpeg developers
(...)
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x562815cf6840] moov atom not found
20191025_141707.no_moov.mp4: Invalid data found when processing input

my_user@my_desktop ~/temp % git clone https://github.com/ponchio/untrunc.git
Cloning into 'untrunc'...
remote: Enumerating objects: 7, done.
remote: Counting objects: 100% (7/7), done.
remote: Compressing objects: 100% (7/7), done.
remote: Total 352 (delta 2), reused 0 (delta 0), pack-reused 345
Receiving objects: 100% (352/352), 178.19 KiB | 833.00 KiB/s, done.
Resolving deltas: 100% (215/215), done.

my_user@my_desktop ~/temp % cd untrunc

my_user@my_desktop ~/temp/untrunc % docker build -t untrunc .
Sending build context to Docker daemon  393.2kB
Step 1/13 : FROM ubuntu
latest: Pulling from library/ubuntu
22e816666fd6: Pull complete
079b6d2a1e53: Pull complete
11048ebae908: Pull complete
c58094023a2e: Pull complete
Digest: sha256:a7b8b7b33e44b123d7f997bd4d3d0a59fafc63e203d17efedf09ff3f6f516152
Status: Downloaded newer image for ubuntu:latest
---> cf0f3ca922e0
Step 2/13 : RUN apt-get update
---> Running in 797ba72456d3
Get:1 http://archive.ubuntu.com/ubuntu bionic InRelease [242 kB]
Get:2 http://security.ubuntu.com/ubuntu bionic-security InRelease [88.7 kB]
(...)
Removing intermediate container 217467dbc655
---> fb0841807f02
Step 12/13 : WORKDIR /untrunc-master
---> Running in 1c5efbf42e3a
Removing intermediate container 1c5efbf42e3a
---> 2910f19b1a3d
Step 13/13 : ENTRYPOINT ["./untrunc"]
---> Running in 407b06462b9d
Removing intermediate container 407b06462b9d
---> 38167b040734
Successfully built 38167b040734
Successfully tagged untrunc:latest

my_user@my_desktop ~/temp/untrunc % cd ..

my_user@my_desktop ~/temp % docker run --rm -u "$(id -u):$(id -g)" -v "$(pwd):/files" untrunc /files/20191025_141723.mp4 /files/20191025_141707.no_moov.mp4
Reading: /files/20191025_141723.mp4
Opening: /files/20191025_141723.mp4
Repair: /files/20191025_141707.no_moov.mp4
Track 0 codec: mp4a
Track 0 codec: mp4a
Track 0 codec: mp4a
(...)

mp4a: Failure because of NULL header.
avc1: Match with 0 header.

Buffer size exceeded (52675 > 52117).
Track 0 codec: mp4a
Track 1 codec: avc1
Buffer size exceeded (52675 > 52117).
Found 830 packets.

Saving to: /files/20191025_141707.no_moov.mp4_fixed.mp4
Track 0 (mp4a): duration: 520192 timescale: 48000
Adjusting track duration to movie timescale: New duration: 10838 timescale: 1000.
Track 1 (avc1): duration: 965861 timescale: 90000
Adjusting track duration to movie timescale: New duration: 10732 timescale: 1000.
Movie duration: 10838 timescale: 1000

my_user@my_desktop ~/temp % AtomicParsley 20191025_141707.no_moov.mp4_fixed.mp4 -T
Atom ftyp @ 0 of size: 24, ends @ 24
Atom moov @ 24 of size: 14633, ends @ 14657
     Atom mvhd @ 32 of size: 108, ends @ 140
     Atom udta @ 140 of size: 66, ends @ 206
         Atom SDLN @ 148 of size: 16, ends @ 164                                         ~
         Atom smrd @ 164 of size: 16, ends @ 180                                         ~
         Atom smta @ 180 of size: 26, ends @ 206                                         ~
     Atom meta @ 206 of size: 176, ends @ 382
         Atom  @ 218 of size: 19215253, ends @ 19215471                                         ~
     Atom trak @ 382 of size: 5724, ends @ 6106
             Atom tkhd @ 390 of size: 92, ends @ 482
             Atom mdia @ 482 of size: 5624, ends @ 6106
                 Atom mdhd @ 490 of size: 32, ends @ 522
                 Atom hdlr @ 522 of size: 44, ends @ 566
                 Atom minf @ 566 of size: 5540, ends @ 6106
                     Atom vmhd @ 574 of size: 20, ends @ 594
                     Atom dinf @ 594 of size: 36, ends @ 630
                         Atom dref @ 602 of size: 28, ends @ 630
                     Atom stbl @ 630 of size: 5476, ends @ 6106
                         Atom stsd @ 638 of size: 176, ends @ 814
                             Atom avc1 @ 654 of size: 160, ends @ 814
                                 Atom avcC @ 740 of size: 39, ends @ 779
                                 Atom pasp @ 779 of size: 16, ends @ 795                         ~
                         Atom stts @ 814 of size: 2592, ends @ 3406
                         Atom stss @ 3406 of size: 60, ends @ 3466
                         Atom stsz @ 3466 of size: 1308, ends @ 4774
                         Atom stsc @ 4774 of size: 28, ends @ 4802
                         Atom stco @ 4802 of size: 1304, ends @ 6106
     Atom trak @ 6106 of size: 8551, ends @ 14657
             Atom tkhd @ 6114 of size: 92, ends @ 6206
             Atom mdia @ 6206 of size: 8451, ends @ 14657
                 Atom mdhd @ 6214 of size: 32, ends @ 6246
                 Atom hdlr @ 6246 of size: 44, ends @ 6290
                 Atom minf @ 6290 of size: 8367, ends @ 14657
                     Atom smhd @ 6298 of size: 16, ends @ 6314
                     Atom dinf @ 6314 of size: 36, ends @ 6350
                         Atom dref @ 6322 of size: 28, ends @ 6350
                     Atom stbl @ 6350 of size: 8307, ends @ 14657
                         Atom stsd @ 6358 of size: 91, ends @ 6449
                             Atom mp4a @ 6374 of size: 75, ends @ 6449
                                 Atom esds @ 6410 of size: 39, ends @ 6449                         ~
                         Atom stts @ 6449 of size: 4080, ends @ 10529
                         Atom stsz @ 10529 of size: 2052, ends @ 12581
                         Atom stsc @ 12581 of size: 28, ends @ 12609
                         Atom stco @ 12609 of size: 2048, ends @ 14657
Atom mdat @ 14657 of size: 19200814, ends @ 19215471

~ denotes an unknown atom
------------------------------------------------------
Total size: 19215471 bytes; 45 atoms total. AtomicParsley version: 0.9.0 (utf8)
Media data: 19200814 bytes; 14657 bytes all other atoms (0.076% atom overhead).
Total free atom space: 0 bytes; 0.000% waste.
------------------------------------------------------

my_user@my_desktop ~/temp % ffmpeg -i 20191025_141707.no_moov.mp4_fixed.mp4
ffmpeg version 4.2.1-0york0~18.04.1 Copyright (c) 2000-2019 the FFmpeg developers
(...)
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '20191025_141707.no_moov.mp4_fixed.mp4':
  Metadata:
    major_brand     : mp42
    minor_version   : 0
    compatible_brands: isommp42
    creation_time   : 2019-10-25T12:17:31.000000Z
    com.android.version: 9
    com.android.capture.fps: 30.000000
  Duration: 00:00:10.84, start: 0.000000, bitrate: 14183 kb/s
    Stream #0:0(eng): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709/bt709/smpte170m), 1920x1080, 14054 kb/s, SAR 1:1 DAR 16:9, 30 fps, 30 tbr, 90k tbn, 180k tbc (default)
    Metadata:
      creation_time   : 2019-10-25T12:17:31.000000Z
      handler_name    : VideoHandle
    Stream #0:1(eng): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 256 kb/s (default)
    Metadata:
      creation_time   : 2019-10-25T12:17:31.000000Z
      handler_name    : SoundHandle
At least one output file must be specified


If you need just the commands, then here's a list with explanation:
  1. First we create a "bad" video from a good one. For this we print out the tree of mp4/mov atoms with AtomicParsley:
    AtomicParsley 20191025_141707.mp4 -T
  2. We cut off the moov atom and a few bytes more from the end of the video:
    dd if=20191025_141707.mp4 bs=19252987 count=1 of=20191025_141707.no_moov.mp4
  3. We check out Untrunc.
    git clone https://github.com/ponchio/untrunc.git
  4. We build the Docker image.
    cd untrunc && docker build -t untrunc .
  5. Run the container with a few parameters.
    We need -u "$(id -u):$(id -g)" so untrunc will have read+write access to it's input files and the current working directory (for the output file).
    We mount the current working directory with -v "$(pwd):/files" so untrunc can reach the files and the directory.
    cd .. && docker run --rm -u "$(id -u):$(id -g)" -v "$(pwd):/files" untrunc /files/20191025_141723.mp4 /files/20191025_141707.no_moov.mp4
  6. We check the atom tree of the "fixed" video.
    AtomicParsley 20191025_141707.no_moov.mp4_fixed.mp4 -T
It all worked pretty well. I could open the resulting file in just about any player (VLC, mpv2, browsers, etc.).
On the homepage of the tool Federico writes that it is very specific for h.264 video and aac audio codecs and of course mov/mp4 containers. But most/many cameras and phones use exactly this combination to record videos so it's applicable in many situations.

Syndicate content