Better Insta360 X Series support

The Insta 360 X5 camera is a milestone in spherical distortion correction. The X5 features initial approaches to a converter that makes .inf data directly usable for Mapillary.

@osmplus_org - something seems off with that calculation. Mapillary samples about 1 image every 3 meters (unless you’re going highway speeds, in which case it is more sparse). So ideally the number should be closer to 0.333 images per meter. If you look at your actual captures on Mapillary I assume you’re seeing the correct sampling rate of about 1 image every 3 meters?

1 Like

Not only that, by using OpenStreetMap data where there is no GPS reception, I can now also master tunnel passages without interruption. https://www.mapillary.com/app/?pKey=1073402984628753

1 Like

@osmplus_org - just to make sure I understand, are you saying that the .gpx track you recorded with osmAnd was able to record accurate GPS through a tunnel? Is this because you have OsmAnd connected to a ODB2 Bluetooth adapter?

The topic of tunnels deserves a separate discussion thread. Suffice it to say, osmand plays no role here.

Generally Mapillary currently samples 1 image every 3 meters, with some variation in the mobile clients vs server processing. However, we’re also working on image-based sampling, where we will sample when the scene changes. On average I think it will still be around 1 image every 3 meters or so.

1 Like

I would like to use the GPX track recorded by the GPX remote, but unfortunately, its super-fine GPX resolution overloads Mapillary, and even though I upload videos, very few images are imported into Mapillary. Tracks recorded with osmand are a solution, (OSMAnd only generates one GPX point per second, a much lower number than Insta Remote. Spoiler Mapillay is encouraged to interpolate and fill in the gaps due to the lower number of GPX points, producing a satisfactory result with OSMAnd GPX tracks.) but the effort required to create a sequence that matches the video is quite significant. Unfortunately, a smartphone only creates approximate GPX tracks, and the track often leaves the road with osmand.

I’m currently trying various methods to reduce the number of GPX points recorded with the Insta remote. Initial results are promising https://www.mapillary.com/app/?lat=47.246145041667006&lng=11.395493350000038&z=17&focus=photo&all_coverage=false&x=0.7348641887117382&y=0.593100773568436&zoom=0&pKey=647831611247148&panos=true&mapStyle=OpenStreetMap
This is a combination of manual correction of GPX nodes via JOSM editor intervention, and mechanical post-processing using a VBA macro, which reduces the node density of the Insta 360 Remote GPX track and adds missing times to the manually added nodes in the tunnel. I’m still working on the optimized reduction of Insta Remote GPX points; for testing purposes, the GPX node density is reduced by a factor of 8. The goal is to achieve the desired image density of three meters of driving distance per image.

My current conclusion, which in my case is currently producing promising results.
Copy the contents of the Insta 360 X3 SD card to a terabyte SSD drive. Structure the Insta raw data into groups of up to 2.5 hours of recording time. To do this, I create the following subdirectories: 1, 5, 10, 15, 20, and 25, into which I move the Insta raw data. This means that directory 1 will contain Insta raw data 1, 2, 3, and 4, and directory 5 will contain Insta raw data 5, 6, 7, 8, and 9.
I then load only one group at a time into the InstaStudio software. This ensures that the Insta software runs stably and efficiently. If I export video files, such a group fits easily into a terabyte SSD drive (600 gigabytes of storage space required for a 2.5-hour drive). When rendering the Insta videos, I create segments with a maximum length of 5.50 minutes each. Longer videos generate numbers of more than 2000 GPX points in Mapillary. Mapillary has difficulty processing such videos, and they then get stuck in yellow in the timeline Processing times - #25 by eserte.
So I only created segments with a maximum drive time of 6 minutes. As a reward, I can output high-quality mov files instead of mp4 for better image quality.

I then reduce the Insta 360 GPX track by a factor of 10. In a subsequent check of the GPX track using the (OpenStreetMap) JOSM editor, I check for outliers. I cut out faulty sections, for example, due to a tunnel, and redraw the gaps by hand.
A final VBA script fills in the manually added data. nodes again with an interpolated time. My script uses the last usable original GPX time and the beginning of the GPX continuation.

2 Likes

Before I begin all this, I run the following VBA script in Excel.
Insta Studio generates terrible file names. Nobody understands why the second export set has the appendix “(1)” and is uploaded to Mapillary before the first export set. This makes checking the upload process later a nightmare. My script adds “(0)” to the first export set, thus fixing the sorting of the records. The slightly shortened and adjusted file name is more readable.

Sub A_BatchCleanVIDFileNames()
    Dim fso As Object, folderPath As String, file As Object
    Dim fileName As String, baseName As String, ext As String
    Dim parts() As String
    Dim datePart As String, timePart As String, seqPart As String
    Dim newBase As String, newName As String
    Dim dt As Date, weekdayName As String
    Dim counter As Integer, finalName As String

    ' Select folder
    With Application.FileDialog(msoFileDialogFolderPicker)
        .Title = "Select folder containing VID files"
        If .Show <> -1 Then Exit Sub
        folderPath = .SelectedItems(1)
    End With

    Set fso = CreateObject("Scripting.FileSystemObject")

    ' Loop through all files in the folder
    For Each file In fso.GetFolder(folderPath).Files
        fileName = file.Name
        ext = LCase(fso.GetExtensionName(fileName))

        ' Only process relevant files starting with VID_, skip Apple fragments
        If (ext = "gpx" Or ext = "mov" Or ext = "mp4") And Left(fileName, 4) = "VID_" And Left(fileName, 2) <> "._" Then
            baseName = fso.GetBaseName(fileName)

            ' Skip already renamed files
            If InStr(baseName, "-") > 0 And InStr(baseName, "(") > 0 Then
                GoTo SkipFile
            End If

            parts = Split(baseName, "_")
            If UBound(parts) >= 4 Then
                datePart = parts(1)
                timePart = parts(2)

                ' Remove bracket content from sequence part
                If InStr(parts(4), "(") > 0 Then
                    parts(4) = Left(parts(4), InStr(parts(4), "(") - 1)
                End If
                seqPart = parts(4)

                ' Calculate weekday and remove dot
                On Error Resume Next
                dt = DateSerial(Left(datePart, 4), Mid(datePart, 5, 2), Right(datePart, 2))
                weekdayName = Replace(Format(dt, "ddd"), ".", "") ' e.g. "Sa" instead of "Sa."
                On Error GoTo 0

                ' Convert sequence to numeric value
                seqPart = CStr(Val(seqPart))

                ' Build base name without counter
                newBase = datePart & timePart & seqPart & "_" & _
                          Right(datePart, 2) & "_" & Mid(datePart, 5, 2) & "-" & weekdayName & "-" & Format(seqPart, "00")

                ' Increment counter until unique filename is found
                counter = 0
                Do
                    finalName = newBase & "(" & counter & ")." & ext
                    counter = counter + 1
                Loop While fso.FileExists(fso.GetParentFolderName(file.Path) & "\" & finalName)

                ' Rename file
                file.Name = finalName
            End If
        End If
SkipFile:
    Next file

    MsgBox "Filenames successfully restructured.", vbInformation
End Sub

If you prefer Python code, you can translate this code into Python. I prefer Excel because the process is clearer for me, but that’s a matter of taste. And by the way, I’m no coding genius; I explained exactly what I needed to Microsoft Copilot. And Copilot wrote this code. You have to tame an AI first; once tamed, it actually writes useful code, sometimes.

1 Like

Finally a democratic script.

1 Like

I choose ProRes because Google partially accepts my Insta360 X3 tunnel footage. I find it astonishing that a cheap camera outperforms professional cameras in certain situations. How does that compare with an Insta360 X5? It’s obviously worth sticking with the best possible quality. If Mapillary encodes the quality into another format itself, it will probably use a good hardware encoder for this. We’ll leave that to Mapillary. As a 360-degree enthusiast, you have to accept that cameras with a limited field of view deliver better image quality. Especially if you have difficulty reading the text on captured signs due to the lack of 360 resolution, then perhaps a better color space will help.

Regarding Excel: I change the code I use almost daily, partly to further optimize the workflow, and partly because there are many unknown variables at play, which is why almost every day brings new insights, and I have Copilot modify the code I use.

Copilot, however, does a lot of nonsense, so I need to be able to read the code to steer it in the right direction. While variables are lightweight, we humans can’t grasp their content. Excel is my display that shows me intermediate and calculated results. A functioning end application can always be reduced to pure, lightweight script code. Perhaps Mapillary will integrate the reduction of GPX points and the filling of missing times into a future desktop uploader, who knows.

My latest discovery is that the points interpolated by Mapillary between my GPX points follow the curvature of the road. Mapillary uses the GPX points I reduced as beacons, but there’s a lot going on in between that we don’t yet know. I suspect that Mapillary is using the GPX information contained in the video image there.

My current steps for perfect Mapillary shots with the Insta360 X3

Preparation:

  1. Record to a 512 GB Micro SD card that supports 200 Mbps. This should be enough for a day, and at 200 Mbps, there are only short breaks every 30 minutes. Sort your recordings into subfolders: 1-4, 5-9, 10-14, 15-19, 20-24. For optimal performance, open a maximum of four recordings in Insta Studio at a time. Export 360 degree videos, with a maximum length of 5.50 minutes each.

After exporting through Insta Studio:
2. Missing (0) are added.
3. Files are labeled with the recording time of the first GPX point.
4. I load the GPX tracks into the JOSM editor. I replace faulty sections with a hand-drawn way, choosing the number of nodes so that the interval remains under three seconds. I try to distribute the hand-drawn nodes evenly.
5. Next, the nodes are reduced by a factor of 10; manually added nodes without time information are not reduced.
6. A script now determines the last time and the continuation of gaps and adds an interpolated time to my hand-drawn nodes.
7. The edited Excel column content is exported as a GPX file.

An Excel VBA code that labels the Insta360 export with the correct recording time. The code extracts the recording date from the first GPX track found. Note: This code moves the data to a new directory.
This code is experimental and automatically generates the required Excel worksheets. The code should only be used on test data. No liability is assumed for data loss.

Sub A_BatchCleanVIDFileNames()
    Dim fso As Object, folderPath As String, file As Object
    Dim fileName As String, baseName As String, ext As String
    Dim parts() As String, seqPart As String, appendixPart As String
    Dim dt As Date, weekdayName As String
    Dim counter As Integer, vidCount As Long
    Dim parentFolder As String, cleanupFolder As String
    Dim gpxDate As Date, gpxFilePath As String
    Dim ws As Worksheet
    Dim timeToken As String
    Dim importDate As String, importWeekday As String, prefixDate As String
    Dim seqOnly As String, finalName As String
    Dim seqMap As Object
    Const MAX_SIZE_BYTES As Double = 60# * 1024# * 1024# * 1024# ' 60 GB

    ' === Verzeichnis auswählen ===
    With Application.FileDialog(msoFileDialogFolderPicker)
        .Title = "Select folder containing VID files"
        If .Show <> -1 Then Exit Sub
        folderPath = .SelectedItems(1)
    End With

    Set fso = CreateObject("Scripting.FileSystemObject")
    parentFolder = fso.GetParentFolderName(folderPath)
    timeToken = Format(Now, "yyyymmddhhmmss")
    cleanupFolder = parentFolder & "\Upload" & timeToken

    ' === Zielordner erzeugen ===
    If Not fso.FolderExists(cleanupFolder) Then fso.CreateFolder cleanupFolder

    ' === Dateien verschieben ===
    vidCount = 0
    For Each file In fso.GetFolder(folderPath).Files
        If Left(file.Name, 4) = "VID_" Then
            file.Move cleanupFolder & "\" & file.Name
            vidCount = vidCount + 1
        End If
    Next file

    If vidCount = 0 Then
        MsgBox "Keine VID_-Dateien gefunden. Vorgang abgebrochen.", vbExclamation
        Exit Sub
    End If

    ' === Textdatei im Ursprungsverzeichnis hinterlassen ===
    Dim transferFile As Object, logText As String
    logText = "Transfer erfolgreich abgeschlossen." & vbCrLf & vbCrLf & _
              "Alle relevanten VID_-Dateien wurden am " & Format(Now, "yyyy-mm-dd") & _
              " um " & Format(Now, "hh:mm:ss") & " in das Verzeichnis:" & vbCrLf & _
              "A_Cleanup_and_Renamed" & timeToken & vbCrLf & vbCrLf & _
              "Dieses Verzeichnis wurde automatisch erstellt, um den Workflow zu strukturieren und Dateifragmente zu isolieren."

    Set transferFile = fso.CreateTextFile(folderPath & "\Transfer to A_Cleanup_successful.txt", True)
    transferFile.WriteLine logText
    transferFile.Close
    Set transferFile = Nothing

    ' === GPX-Zeitinformation aus erster Datei extrahieren ===
    Set ws = Worksheets("GPX_Rename")
    For Each file In fso.GetFolder(cleanupFolder).Files
        If LCase(fso.GetExtensionName(file.Name)) = "gpx" Then
            gpxFilePath = file.Path
            gpxDate = GetFirstTrackTime(gpxFilePath)
            If gpxDate <> 0 Then
                ws.Range("E2").value = Format(gpxDate, "yyyy-mm-dd hh:mm:ss")
                ws.Range("F2").value = Format(gpxDate, "dd.mm.yyyy")
                ws.Range("G2").value = Format(gpxDate, "hh:mm:ss")
                ws.Range("H2").value = Format(gpxDate, "ddd")
                Exit For
            End If
        End If
    Next file

    ' === Zeitinformationen aus GPX_Rename holen ===
    importDate = Format(ws.Range("F2").value, "yyyy_mm_dd")
    importWeekday = Replace(ws.Range("H2").value, ".", "")
    prefixDate = importDate & "_" & importWeekday
    Set seqMap = CreateObject("Scripting.Dictionary")

    ' === Umbenennung aller Dateien ===
    For Each file In fso.GetFolder(cleanupFolder).Files
        fileName = file.Name
        ext = LCase(fso.GetExtensionName(fileName))
        baseName = fso.GetBaseName(fileName)

        ' === Schritt 1: Appendix prüfen und ggf. (0) anhängen ===
        If InStr(baseName, "(") = 0 Then
            file.Name = baseName & "(0)." & ext
            baseName = fso.GetBaseName(file.Name)
        End If

        ' === Schritt 2: Zeitinformationen entfernen ===
        parts = Split(baseName, "_")
        If UBound(parts) >= 4 Then
            seqPart = parts(4)
            If InStr(seqPart, "(") > 0 Then
                seqPart = Left(seqPart, InStr(seqPart, "(") - 1)
            End If
            appendixPart = Mid(baseName, InStr(baseName, "(")) ' z. B. "(0)"
            seqOnly = Format(Val(seqPart), "00")

            ' === Schritt 3: Sequenzzählung prüfen ===
            If Not seqMap.exists(seqOnly) Then
                seqMap(seqOnly) = 0
            Else
                seqMap(seqOnly) = seqMap(seqOnly) + 1
            End If

            ' === Schritt 4: Finalen Namen erzeugen ===
            finalName = prefixDate & "-" & seqOnly & appendixPart & "." & ext
            file.Name = finalName
        End If
    Next file

    ' === Verbindung freigeben ===
    Set fso = Nothing
    Set file = Nothing

    MsgBox "Alle Dateien wurden nach dem Aufnahmetag benannt. Nun solltest du die GPX Spuren mit dem JOSM Editor prüfen, findest du Tunnellücken, ergänze deren Verlauf von Hand, fehlerhafte GPX Ausreisser vorher löschen.HInweis: JOSM benötigt eine vorherige Installation von JAVA eclipse-jee-2025-06-R-win32-x86_64", vbInformation

Shell "explorer.exe """ & cleanupFolder & """", vbNormalFocus

End Sub



' ============================================
' Modul: modLogger
' Purpose: Prepare and manage the GPX_Rename worksheet
' Author: osmplus.org
' Version: 1.2
' ============================================

Function InitRenameWorksheet() As Worksheet
    Dim ws As Worksheet

    On Error Resume Next
    Set ws = ThisWorkbook.Worksheets("GPX_Rename")
    If ws Is Nothing Then
        Set ws = ThisWorkbook.Worksheets.Add
        If Not ws Is Nothing Then ws.Name = "GPX_Rename"
    End If
    On Error GoTo 0

    ' Sicherheitsprüfung: Falls ws immer noch Nothing ist
    If ws Is Nothing Then
        MsgBox "Fehler: Das Worksheet 'GPX_Rename' konnte nicht erstellt werden.", vbCritical, "Initialisierung fehlgeschlagen"
        Exit Function
    End If

    ' Worksheet bereinigen und vorbereiten
    ws.Cells.Clear
    ws.Activate

    ' Spaltenüberschriften setzen
    ws.Range("A1:N1").value = Array( _
        "Counter", _
        "Group Index", _
        "Original Filename", _
        "File Type", _
        "GPX Timestamp", _
        "Import Date", _
        "Import Time", _
        "Weekday (GPX)", _
        "Weekday (Fallback)", _
        "Sequence", _
        "New Filename", _
        "Target Sequence", _
        "Prefix", _
        "Export Status" _
    )

    ' Rückgabe des vorbereiteten Worksheets
    Set InitRenameWorksheet = ws
End Function



' ============================================
' Modul: modHelpers
' Purpose: Utility functions for GPX parsing and string extraction
' Author: osmplus.org
' Version: 1.1
' ============================================

Function GetFirstTrackTime(gpxFilePath As String) As Date
    Dim xmlDoc As Object
    Dim trkptNodes As Object
    Dim timeNode As Object
    Dim timeText As String

    On Error GoTo ErrHandler

    ' Lade GPX-Datei als XML
    Set xmlDoc = CreateObject("MSXML2.DOMDocument.6.0")
    xmlDoc.async = False
    xmlDoc.Load gpxFilePath

    If xmlDoc.ParseError.ErrorCode <> 0 Then
        GetFirstTrackTime = 0
        Exit Function
    End If

    ' Namespace definieren
    xmlDoc.SetProperty "SelectionNamespaces", "xmlns:gpx='http://www.topografix.com/GPX/1/1'"

    ' Erster <trkpt>-Eintrag
    Set trkptNodes = xmlDoc.SelectNodes("//gpx:trkpt")
    If trkptNodes.Length > 0 Then
        Set timeNode = trkptNodes.Item(0).SelectSingleNode("gpx:time")
        If Not timeNode Is Nothing Then
            timeText = timeNode.Text
            timeText = Replace(timeText, "T", " ")
            timeText = Replace(timeText, "Z", "")
            If IsDate(timeText) Then
                GetFirstTrackTime = CDate(timeText)
                Exit Function
            End If
        End If
    End If

    GetFirstTrackTime = 0
    Exit Function

ErrHandler:
    GetFirstTrackTime = 0
End Function

Function ExtractTimeValue(xmlLine As String) As String
    Dim startPos As Long, endPos As Long
    startPos = InStr(xmlLine, "<time>") + 6
    endPos = InStr(xmlLine, "</time>")
    If startPos > 6 And endPos > startPos Then
        ExtractTimeValue = Mid(xmlLine, startPos, endPos - startPos)
    Else
        ExtractTimeValue = ""
    End If
End Function

Hi folks, we have edited the Insta360 X series instructions to recommend using “Screen Lock” during recording to increase GPS accuracy of timelapse videos.

”If you are using your phone as the GPS source for your Insta360 videos (and not the standalone GPS remote), ensure that you enable the “Screen Lock” during recording by tapping on the lock icon in the top right of the preview screen. Do not leave the Insta360 app during recording. Leaving the app will increase the chances of inaccurate GPS. To disable Screen Lock, long press on the icon again.”

Have you had experience with timelapse videos and the screen lock feature?

Please forgive my ignorance but are you sure about what “Screen Lock” in the Insta360 app does? Does it lock just the touch screen on the camera or does it lock the Android (potentially also iOS) Insta360 app’s screen from being grabbed by other apps?

Since Insta360 cameras apparently appreciate some level of popularity among Mapillarians, why don’t you add support for uploading .insv videos directly and run the Insta360 Studio re‑projection step on the backend? Is it an Insta360 Studio license thing or is it about being able to automate Insta360 Studio?

@GITNE - yes, the “Screen Lock” feature seems to keep the device awake to prevent it from going to sleep, and to prevent mistaps. The user still has to keep the Insta360 app open in the foreground (which we also added in the instructions).

In terms of uploading .insv directly - that’s something we intend to take a look at as well.

2 Likes