iOS: recorded video location is written without ISO 6709 fixed-width degrees, Photos drops it
Maintainers usually reply within 3 days
Nobody has claimed this yet.
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 80/100
Research direction
The fix lives in ios/Extensions/CoreLocation/CLLocation+toISO6709String.swift, where latPart and lonPart are formatted with %+.Nf around the normalizeNegZero calls. Start there and change the format so the degrees are zero-padded to fixed widths (2 for latitude, 3 for longitude), keeping the fraction digits. Done when a recorded video's com.apple.quicktime.location.ISO6709 item reads a padded string such as +48.838800+002.378600/ and Photos places it on the map.
Written by the indexing model from the issue text.
Description
Prerequisites
- I have read and followed every applicable step in the Nitro Modules Troubleshooting guide.
- I have read the VisionCamera Troubleshooting guide.
- I have searched existing issues and found nothing matching.
- I am on the latest version of react-native-vision-camera (5.2.3).
What happened
A video recorded with createRecorder({ location }) on iOS carries its position in the com.apple.quicktime.location.ISO6709 metadata item, but the string is written without the fixed-width degrees ISO 6709 Annex H requires. CLLocation+toISO6709String.swift formats both coordinates with "%+.\(fractionalDigits)f", so a position in Paris becomes +48.838800+2.378600/.
Apple's own QuickTime example is +27.5916+086.5640+8850/: two digits for the latitude degrees, three for the longitude degrees, zero-filled. When the longitude (or the latitude) has fewer digits than that, the Photos library drops the whole location on import: the video shows no place on the map and no location in its info panel. Any video shot at a longitude between -10° and 10° (Western Europe, West Africa, the UK…) or a latitude between -10° and 10° is affected. The same file with the padded string (+48.838800+002.378600/) is placed correctly.
Steps to reproduce
- On iOS, record a video with
createRecorder({ location }), with the device in Paris (or any position with a longitude between -10° and 10°, e.g. a simulated48.8388, 2.3786). - Save the resulting file to the camera roll (PHPhotoLibrary / expo-media-library).
- Open the Photos app on the video.
What did you expect to happen?
The video is placed on the map in Photos, like one recorded by the Camera app.
What actually happened?
Photos shows no location for the video. The file's com.apple.quicktime.location.ISO6709 item reads +48.838800+2.378600/.
Fix
Give the degrees their fixed width, zero-filled (sign + 2 digits for the latitude, sign + 3 for the longitude, plus the fraction). This is the patch we ship through pnpm patch:
--- a/ios/Extensions/CoreLocation/CLLocation+toISO6709String.swift
+++ b/ios/Extensions/CoreLocation/CLLocation+toISO6709String.swift
@@ -34,9 +34,13 @@ extension CLLocation {
let latN = normalizeNegZero(lat)
let lonN = normalizeNegZero(lon)
- // No field widths needed; the important part is forced sign and fixed fraction digits.
- let latPart = String(format: "%+.\(fractionalDigits)f", latN)
- let lonPart = String(format: "%+.\(fractionalDigits)f", lonN)
+ // ISO 6709 Annex H gives the degrees a fixed length, zero-filled: two digits for the latitude,
+ // three for the longitude, as in Apple's QuickTime example "+27.5916+086.5640+8850/". The Photos
+ // library drops the whole tag otherwise: a video shot at longitude "+2.378600" (Paris) or
+ // latitude "+7.046953" is imported without a location.
+ let fractionWidth = fractionalDigits > 0 ? fractionalDigits + 1 : 0
+ let latPart = String(format: "%+0\(3 + fractionWidth).\(fractionalDigits)f", latN)
+ let lonPart = String(format: "%+0\(4 + fractionWidth).\(fractionalDigits)f", lonN)
var s = latPart + lonPart
Happy to open a PR with it if you want.
Affected platforms
- iOS
- Android
Device(s) affected
iPhone; the unpadded tag is also visible on the simulator by saving the file and inspecting it.
VisionCamera version
5.2.3
React Native version
0.86.3 (Expo SDK 57)
React Native architecture
New Architecture (Nitro)
Features being used
- Video capture
- Dominant language
- TypeScript
- Stars
- 9.6k
- Forks
- 1.4k
- Avg merge
- 16h 53m
- Merged PRs (30d)
- 1
Getting set up
This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from margelo/react-native-vision-camera
-
Android (vision-camera-location): HybridLocationManager never quits its HandlerThread on disposeOpen
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
margelo/react-native-vision-camera#4217 ·
Maintainers usually reply within 3 days
-
🐛 bug
Difficulty 2/5 1-3 hours Newbie friendliness 66/100
margelo/react-native-vision-camera#4211 ·
Maintainers usually reply within 3 days
-
🐛 bug
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
margelo/react-native-vision-camera#4096 · 3 comments ·
Maintainers usually reply within 3 days
-
🐛 bug
Difficulty 4/5 3-5 days Newbie friendliness 20/100
margelo/react-native-vision-camera#4219 ·
Maintainers usually reply within 3 days
-
🐛 bug
Difficulty 3/5 1-2 days Newbie friendliness 70/100
margelo/react-native-vision-camera#4213 ·
Maintainers usually reply within 3 days
All issues in margelo/react-native-vision-camera
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
wormhole-foundation/wormhole#5062 ·
Maintainers usually reply within 1 day
-
internal os specific
Difficulty 2/5 1-3 hours Newbie friendliness 65/100
frostney/GocciaScript#1688 ·
Maintainers usually reply within 1 day
-
integration:hermes
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
vectorize-io/hindsight#5592 ·
Maintainers usually reply within 1 day
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
vercel/streamdown#673 · 1 reaction ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
apache/rocketmq-dashboard#6712 ·
Maintainers usually reply within 3 days