I copied a test clip with ffmpeg, changing nothing but the container, and the copy came out still saying where the clip was recorded while no longer saying when. That is the opposite of what most people want from a quick clean-up before sending a video to someone, and it is easy to miss, because the picture is identical and nothing on screen tells you the file's metadata moved.
This piece is about location data inside phone video files: where Android's recording API puts it, how to read it with ffprobe, and which ffmpeg commands remove it while keeping the recording time. I build a camera app for old Android phones. I am not describing how my app or any other app writes files; every result below comes from a clip I generated and tagged myself, with the commands shown so you can run them on your own footage.
Where the coordinates go
Android's MediaRecorder class documents a method for exactly this. Its reference page says setLocation will "Set and store the geodata (latitude and longitude) in the output file." It then says where and in what form: "The geodata is stored in udta box if the output format is OutputFormat.THREE_GPP or OutputFormat.MPEG_4, and is ignored for other output formats." And: "The geodata is stored according to ISO-6709 standard."
Three things follow from those sentences.
- The location lives in the container, in a user-data box, separate from the video frames. You cannot see it by watching the clip, and you cannot remove it by cropping or trimming the picture.
- It is written as text in a standard coordinate notation, a signed latitude followed by a signed longitude. Anything that can read container tags can print it.
- Whether a particular recording carries it depends on the app that made it and on that app's settings. The API makes it possible; it does not make it automatic. The file itself is the reliable witness to what it contains.
A test clip with a known location
To have something to measure, I made two short clips, one MP4 and one MOV, both tagged with a recording time and with coordinates a short walk from the Royal Observatory in Greenwich. Using a public landmark keeps my own location out of the example.
for ext in mp4 mov; do
ffmpeg -v error -f lavfi -i testsrc=size=320x240:rate=15 -t 2 \
-c:v libx264 -pix_fmt yuv420p \
-metadata location="+51.4779-000.0015/" \
-metadata creation_time="2026-10-11T12:00:00Z" "clip.$ext"
done
The testsrc input is a synthetic colour-bar pattern, so the clips are tiny and contain nothing private. Everything below was run with ffmpeg 4.4.2 and Python 3.10.
Reading what a file says about itself
ffprobe prints container tags. Asking for just the two tags this piece is about keeps the output short:
ffprobe -v error -show_entries format_tags=location,creation_time -of default=nw=1 clip.mp4
TAG:creation_time=2026-10-11T12:00:00.000000Z
TAG:location=+51.4779-000.0015/
That is the whole story of the clip in two lines: when it was recorded and where. Point the same command at a real phone recording before you share it. If the location line is there, the coordinates of wherever the phone was standing travel with the file.
The quick copy that keeps the wrong half
The most common thing people do to a video with ffmpeg without re-encoding it is a stream copy into a new file, for example to rename the container or to trim it. Here is the plainest version, followed by the same tag check on the result:
ffmpeg -v error -i clip.mp4 -c copy remux.mp4
ffprobe -v error -show_entries format_tags=location,creation_time -of default=nw=1 remux.mp4
TAG:location=+51.4779-000.0015/
The location came through. The recording time did not.
The first half is documented. The -map_metadata section of the ffmpeg manual says: "By default, global metadata is copied from the first input file, per-stream and per-chapter metadata is copied along with streams/chapters." Location is global metadata, so a plain copy carries it forward.
The second half I can only report, not explain from the text I quoted. With ffmpeg 4.4.2 and no metadata options, creation_time was absent from the output in my runs. I have not checked whether newer releases behave the same way, so treat this as a thing to test on your own build rather than a rule.
For anyone keeping footage as a record, that combination matters. A copied clip that has lost its recording time but kept its coordinates is a worse record and a bigger privacy exposure at the same moment.
Removing everything
The manual also describes the switch that turns automatic copying off: "A negative file index can be used to create a dummy mapping that just disables automatic copying." In practice that is -map_metadata -1:
ffmpeg -v error -i clip.mp4 -c copy -map_metadata -1 stripped.mp4
ffprobe -v error -show_entries format_tags=location,creation_time -of default=nw=1 stripped.mp4 | wc -l
0
The second command counts the tag lines ffprobe prints for the two keys, and the count is zero. Both the location and the recording time are gone.
That is the right call for a clip headed somewhere public, where the time is as personal as the place. It is the wrong call for a clip you might need to rely on later, such as a recording of damage, a delivery or a dispute, where the time is the point.
Keeping the time, dropping the place
The version I would actually use asks for metadata to be copied, then overrides the one key that should not travel by setting it to an empty value. The MP4 file also had a language-suffixed copy of the same tag, so both names are cleared:
for f in clip.mp4 clip.mov; do
out="nolocation.${f##*.}"
ffmpeg -v error -i "$f" -c copy -map_metadata 0 \
-metadata location= -metadata location-eng= "$out"
echo "== $out"
ffprobe -v error -show_entries format_tags=location,creation_time -of default=nw=1 "$out"
done
== nolocation.mp4
TAG:creation_time=2026-10-11T12:00:00.000000Z
== nolocation.mov
TAG:creation_time=2026-10-11T12:00:00.000000Z
Both containers keep their recording time and lose their coordinates. The explicit -map_metadata 0 matters here: it is what brings creation_time back in my runs, in contrast to the bare copy above.
Checking the bytes, not just the tags
A tag reader shows you what it knows how to parse. To be sure the coordinates were removed from the file and not just hidden from one tool, I searched the raw bytes for the two location boxes that turned up in these clips and for the latitude written as text:
import sys
# Byte-level check: does a location box or an ISO 6709 string survive?
MARKERS = {
"loci box": b"loci",
"©xyz box": b"\xa9xyz",
"latitude text": b"+51.4779",
}
for path in sys.argv[1:]:
data = open(path, "rb").read()
found = [name for name, m in MARKERS.items() if m in data]
print(f"{path}: {', '.join(found) if found else 'none of the markers'}")
python3 boxes.py clip.mp4 clip.mov remux.mp4 stripped.mp4 nolocation.mp4 nolocation.mov
clip.mp4: loci box
clip.mov: ©xyz box, latitude text
remux.mp4: loci box
stripped.mp4: none of the markers
nolocation.mp4: none of the markers
nolocation.mov: none of the markers
Two details from that output are worth keeping in mind:
- The two containers stored the same coordinates differently. The MP4 that ffmpeg wrote used a
locibox, and a text search for the latitude finds nothing in it even though the location is present, so the box evidently does not store the coordinates as readable text. The MOV used a©xyzbox with the coordinate string in plain text. A search for the digits alone would have reported the MP4 as clean when it was not. - The plain copy,
remux.mp4, still holds itslocibox, which agrees with the tag check above. The stripped and cleaned files hold none of the three markers.
Finally, I confirmed that none of this touched the picture. Extracting the video stream from three of the files and hashing it gives the same value each time:
for f in clip.mp4 stripped.mp4 nolocation.mp4; do
ffmpeg -v error -i "$f" -map 0:v -c copy -f h264 - | md5sum | cut -c1-12
done
c1d2fe78b45f
c1d2fe78b45f
c1d2fe78b45f
Same frames, different envelope.
A short routine for clips you share
- Run the
ffprobetag check on the file you are about to send. - If a
locationtag is present and the clip is going anywhere public, use the keep-the-time command above, or-map_metadata -1if the time should go as well. - Re-run the tag check on the output, and for anything sensitive, the byte check too.
- Keep the original, untouched, somewhere only you control. The cleaned copy is for sharing; the original is the record.
What I did not establish
- What any particular camera app writes. The Android reference describes what the API can do. Some apps expose a setting for location tags and some do not; the file is the thing to check.
- What happens on upload. I did not test whether any video site, messaging app or phone share sheet removes location from a video file, and I would not assume it does.
- Per-stream tags and other metadata formats. I checked file-level tags and three byte markers. Some phones and editors write additional metadata blocks, and a thorough audit would look for those too.
- Why the plain copy dropped
creation_time. I observed it on one ffmpeg build and did not trace the cause. - How accurate the stored coordinates are on a real recording. A tag can only be as good as the position fix the phone had when it was written.
Try it: Background Camera RemoteStream on Google Play -- record with the screen off and keep the footage on the phone. Setup notes and other write-ups are at superfunicular.com.
Sources. The Android MediaRecorder API reference, setLocation section, and the ffmpeg command-line documentation, -map_metadata section. Quotations are verbatim from both pages as fetched. Test results come from the scripts above, run as shown.
Top comments (0)