Skip to content

Instantly share code, notes, and snippets.

@tmdqfb
Created December 7, 2020 10:34
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save tmdqfb/291c669bcf281b96498987808c155839 to your computer and use it in GitHub Desktop.
Save tmdqfb/291c669bcf281b96498987808c155839 to your computer and use it in GitHub Desktop.
Upload Tesla dashcam videos to mapillary. Requires accompanying GPX file recorded with mobile app or tracker.
#!/usr/bin/python
import os
import sys
import argparse
import gpxpy
import gpxpy.gpx
import subprocess
from pathlib import Path
from datetime import datetime, timedelta
import pytz
from pytz import timezone
TOOLS = 'mapillary_tools' #mapillary tools command (modify with path, version etc. if neeeded)
# Moves videos to folder structure such that they can be processed with mapillary_tools command. A subdirectory per camera (front, back etc.)
def move_to_camera_dir(basepath,camera):
path = os.path.join(basepath,camera)
if not os.path.isdir(path):
os.mkdir(path)
for filename in os.listdir(basepath):
if filename.endswith(camera + ".mp4"):
targetpath = os.path.join(basepath,camera,rchop(filename,"-" + camera + ".mp4"))
if not os.path.isdir(targetpath):
os.mkdir(targetpath)
os.rename(os.path.join(basepath,filename), os.path.join(targetpath,filename))
# Processes videos in a particular directory
def process_camera_dir(basepath,camera,gpx_file,mapillary_username, localtz):
angle = 0
if camera == "back":
angle = 180
elif camera == "left_repeater":
angle = -90
elif camera == "right_repeater":
angle = 90
subfolders = [ f.path for f in os.scandir(os.path.join(basepath,camera)) if f.is_dir() ]
for path in subfolders:
for filename in os.listdir(path):
if filename.endswith(camera + ".mp4"):
tesla_datetime = datetime.strptime(filename[0:19], "%Y-%m-%d_%H-%M-%S") #Pattern: 2020-09-24_14-06-34-front.mp4
tesla_datetime = localtz.localize(tesla_datetime)
milliseconds_since_epoch = tesla_datetime.timestamp()*1000
# 1. Extract frames
subprocess.run([TOOLS, "sample_video", "--import_path", path , "--video_import_path", path , "--video_sample_interval", "0.5", "--video_start_time", str(int(milliseconds_since_epoch)), "--advanced"])
# 2. Add gps, angle etc.
subprocess.run([TOOLS, "process_and_upload", "--advanced", "--import_path", path , "--user_name", mapillary_username , "--geotag_source", "gpx", "--geotag_source_path", gpx_file, "--overwrite_all_EXIF_tags", "--offset_angle", str(angle), "--device_make", "Tesla"])
def rchop(s, suffix):
if suffix and s.endswith(suffix):
return s[:-len(suffix)]
return s
if __name__ == "__main__":
my_parser = argparse.ArgumentParser(description='Process Tesla dashcam videos with accompanying GPX file')
my_parser.add_argument('videopath', metavar='videopath', type=str, help='The videopath to list')
my_parser.add_argument('gpxfilepath',metavar='gpxpath', type=str, help='The gpx file')
my_parser.add_argument('mapillary_user', metavar='mapillary_user', type=str, help='Mapillary username')
my_parser.add_argument('timezone', metavar='timezone', type=str, default="Europe/Zurich", help='Timezone the Tesla ride was in. Default: Europe/Zurich')
args = my_parser.parse_args()
video_dir = args.videopath
gpxpath = args.gpxfilepath
mapillary_user = args.mapillary_user
timezone = args.timezone
if not os.path.isdir(video_dir):
print('The path specified does not exist')
sys.exit()
gpx_file = open(gpxpath, 'r')
gpx = gpxpy.parse(gpx_file)
cameras = ["front", "back", "left_repeater", "right_repeater"]
localtz = timezone
for camera in cameras:
print("Processing camera: **** " + camera + " ****")
print("-- moving source files ---")
move_to_camera_dir(video_dir,camera)
print("-- Processing and uploading videos ---")
process_camera_dir(video_dir,camera,gpxpath,mapillary_user, localtz)
@kimollivier
Copy link

A great start, but a little out of date. The TOOLS options no longer are current. It now needs Python 3.8+ to install.
Line 14 is a bit cryptic. Download the executable e.g. and point to it.
r'd:\download\Mapillary\mapillary_tools-0.11.1-win-64bit.exe'
Line 45 is a string, not a datetime object, it needs to be
tesla_datetime = pytz.timezone(localtz).localize(tesla_datetime) # kmo bugfix 2023-11-02
I had trouble collecting the gpx file. Surely we could get that from the Tesla API now somehow?

@amaiman
Copy link

amaiman commented Nov 5, 2023

A great start, but a little out of date. The TOOLS options no longer are current. It now needs Python 3.8+ to install. Line 14 is a bit cryptic. Download the executable e.g. and point to it. r'd:\download\Mapillary\mapillary_tools-0.11.1-win-64bit.exe' Line 45 is a string, not a datetime object, it needs to be tesla_datetime = pytz.timezone(localtz).localize(tesla_datetime) # kmo bugfix 2023-11-02 I had trouble collecting the gpx file. Surely we could get that from the Tesla API now somehow?

Take a look at my fork of this code at https://gist.github.com/amaiman/448bf52aaf15dea41bf11b82e349d7de - I fixed some of the issues and it's now working for me.

Tesla doesn't log location often enough to get a useful GPX file from their API (or by using something like TeslaFi.). You have to record the GPS using another device. If you have an iPhone, https://github.com/merlos/iOS-Open-GPX-Tracker works well. There are similar apps available for Android.

@kimollivier
Copy link

kimollivier commented Nov 5, 2023

Yes, thanks. I have now got on to the Mapillary tools bugs now. I do have an Android with all sorts of GPS trackers, a Garmin Glo Bluetooth extender and various Garmin handhelds, one with an exernal aerial. They are all a lot of messing about and the phone apps are not very reliable. They drop out or don't start easily. Inside the car the gps signal is poor. The Garmin handheld is reliable, but needs lots of wires and doesn't have any wireless interfaces.
It could be so much better if the GPS coordinates were imbedded in the video by Tesla like every other action camera or even my humble Uniden dashcam. I was just doing a trial before I set up a Rasberry Pi on the Tesla port to automatically upload when at home.

I haven't been able to get the Mapillary tools to work even to sample the video so far. I'm on Windoze 10. I had to download ffmpeg.exe and ffprobe.exe for some reason. Not having much luck so far. I saw the Tesla sample rate of 3 seconds. What a pity there isn't a proper API interface in the car available via the USB port.

Later... success.

@amaiman
Copy link

amaiman commented Nov 5, 2023

It could be so much better if the GPS coordinates were imbedded in the video by Tesla like every other action camera or even my humble Uniden dashcam.

There's a lot of things that Tesla could do that would be nice, but I'm not holding my breath on them ever doing it, unfortunately. I'd love to be able to record the other outside cameras such as the ones that face 90 degrees right/left which would be far more useful for the Mapillary photos.

I believe they intentionally don't record the geodata since then it would in theory be subpoenable. Wouldn't want to get pulled over and have a cop conficate your USB drive as evidence of speeding...

You may want to spin up a Linux VM to do the processing, it's far less hassle then making it all work on Windows. Or use WSL: https://learn.microsoft.com/en-us/windows/wsl/install

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment