Rename file from JSON/Google Takeout

Advanced Renamer forum
#1 : 02/09-20 11:45
Phil
Phil
Posts: 3
Hi all,

I recently created an export of my photos and videos from Google photos using Google Takeout. This gives you all your files plus corresponding JSON files that contain the metadata for each file (e.g MOV_1362.mp4 has MOV_1362.mp4.json)

I've managed to rename all of my photos fine using the "image taken date" for most of my images and exiftool for the rest where it couldn't find one.

However, most of the videos exported have incorrect dates for any date field in their metadata, but the correct date in the corresponding JSON file.

I'm trying to format using the "photoTakenTime>formatted" field in this JSON:

{
"title": "MOV_1362.mp4",
"description": "",
"imageViews": "0",
"creationTime": {
"timestamp": "1478218974",
"formatted": "4 Nov 2016, 00:22:54 UTC"
},
"modificationTime": {
"timestamp": "1587854541",
"formatted": "25 Apr 2020, 22:42:21 UTC"
},
"geoData": {
"latitude": ####,
"longitude": ####,
"altitude": 0.0,
"latitudeSpan": 0.0,
"longitudeSpan": 0.0
},
"geoDataExif": {
"latitude": ####,
"longitude": ####,
"altitude": 0.0,
"latitudeSpan": 0.0,
"longitudeSpan": 0.0
},
"photoTakenTime": {
"timestamp": "1478212929",
"formatted": "3 Nov 2016, 22:42:09 UTC"
}
}

I can only find one forum post about formatting from JSON here but struggled to make it work: https://www.advancedrenamer.com/forum_thread?for um_id=10804

I've got two problems:

1. If I use some simple json, I can get an element fine, like this:

var obj = JSON.parse('{"first_name" : "Sammy", "last_name" : "Shark", "location" : "Ocean"}');
newName = obj.first_name
return newName;

That returns "Sammy" as the filename fine.

If I replace it with the full json from earlier, it doesn't seem to parse (line 0: Syntax error):

var obj = JSON.parse('{
"title": "MOV_1362.mp4",
"description": "",
"imageViews": "0",
"creationTime": {
"timestamp": "1478218974",
"formatted": "4 Nov 2016, 00:22:54 UTC"
},
"modificationTime": {
"timestamp": "1587854541",
"formatted": "25 Apr 2020, 22:42:21 UTC"
},
"geoData": {
"latitude": ####,
"longitude": ####,
"altitude": 0.0,
"latitudeSpan": 0.0,
"longitudeSpan": 0.0
},
"geoDataExif": {
"latitude": ####,
"longitude": ####,
"altitude": 0.0,
"latitudeSpan": 0.0,
"longitudeSpan": 0.0
},
"photoTakenTime": {
"timestamp": "1478212929",
"formatted": "3 Nov 2016, 22:42:09 UTC"
}
}');
newName = obj.title
return newName;

2. I'd need to read each json file rather than pasting it in. If I search online how to do this, I get all sorts of answers:

- "For security purposes, JavaScript is not able to read the local hard drive. You should only have a JSON delivered from a remote server"
- "Use node.js"
etc.

In summary, I imagine the script needs to do this:

- For each file
- Find the corresponding JSON file (filename+json)
- Take the photoTakenTime>formatted value

Any help is much appreciated and I'm sure it would help many other people too as this seems to be a fairly common workflow now that Google shut down their sync tool.

Thanks!


02/09-20 11:45
#2 : 02/09-20 14:19
David Lee
David Lee
Posts: 1125
Try reading from the json file line-by-line using the <FileLine> tag until you reach "photoTakenTime" or the tag returns a null string.

eg

n=1;
do {
line = app.parseTags("<File Line:"+n+">");
if (line.match(/photoTakenTime/)) break;
n++;
}
while (line != "");
app.log(app.parseTags("<File Line:" + (n+2) + ">"));

Extract the timestamp from line n+2, using a regular expression, and use it to rename the .json file. If previously you temporarily rename the .mp4 files to .mp4.txt then you can use pair renaming, which will automatically rename the .txt files to match the renamed .json



02/09-20 14:19 - edited 02/09-20 15:31
#3 : 02/09-20 15:37
Phil
Phil
Posts: 3
Reply to #2:

Hi David,

Thanks for your quick reply.

So to try and understand...this code here:

n=1;
do {
line = app.parseTags("<File Line:"+n+">");
if (line.match(/photoTakenTime/)) break;
n++;
}
while (line != "");

Will essentially iterate through each line of the JSON while there's something there (while line != "") until it finds the text "photoTakenTime". Makes sense so far, except how does it know it's reading the associated JSON file?

For example, my directory looks like this:

MOV_1361.mp4
MOV_1361.mp4.json
MOV_1362.mp4
MOV_1362.mp4.json
MOV_1363.mp4
MOV_1363.mp4.json

etc... So the timestamp element I need is always from filename+".json"

>>Extract the timestamp from line n+2, using a regular expression, and use it to rename the .json file. If previously you temporarily rename the .mp4 files to .mp4.txt then you can use pair renaming, which will automatically rename the .txt files to match the renamed .json

I'm a bit lost with this bit too, apologies - why would I need to rename the .json?

Thanks again.


02/09-20 15:37
#4 : 02/09-20 17:00
David Lee
David Lee
Posts: 1125
Reply to #3:
The method is a workaround because ARen/JavaScript can't read from the filesystem .

Tags only apply to the file in the list that ARen is working on at the time so that you can only use <FileLine> to rename the file that contains the data - ie the json files.

If you select "Pair renaming" then ARen will identify files with the same name but different extensions as "pairs". Paired files will automatically be given the same new name as the dominant member of the "pair". (Note that "pairs" can comprise more than two files with the same base name).

For this to work you must rename either the .mp4 or the .json file such that they both have the same base name.

Whilst it would seem obvious to simply remove the ".mp4" from the .json files this will not work since .mp4 "trumps" .json such that ARen will try to parse the .mp4 file instead.

Hence the suggestion that you rename the .mp4 files to .mp4.txt. You will need to do this in a separate batch, since pairing is based on the original filename. Once you have renamed the .mp4 files add all the file pairs to the List and try this script:

n=1;
do {
line = app.parseTags("<File Line:"+n+">");
if (line.match(/photoTakenTime/)) break;
n++;
}
while (line != "");
match = app.parseTags("<File Line:" + (n+2) + ">").match(/".*"(.*)"/);
return match[1] + ".mp4";

This should rename all the files according to the timestamps in the .json files.

You will see errors, since the timestamps contain ":" as a separator, which is illegal in Windows filenames so add a replace method to change ":" to something like "_". You can also add a replace method to the same batch to remove the .txt extensions.

Sorry that explanation is a bit rushed but I'm about to hit the road for a few days away and don't have much time.

Hope it makes sense!


02/09-20 17:00
#5 : 05/09-20 14:49
Phil
Phil
Posts: 3
Reply to #4:

Hi David,

Thanks for your help - I got there in the end. For anyone who comes across this thread, this was my script in the end:

------------------------------------------------------------------
n=1;
do {
line = app.parseTags("<File Line:"+n+">");
if (line.match(/photoTakenTime/)) break;
n++;
}
while (line != "");
match = app.parseTags("<File Line:" + (n+1) + ">").match(/".*"(.*)"/);

var epoch = new Date(0);
epoch.setUTCSeconds(match[1]);

var day = zpad(epoch.getDate().toString(), 2); //day of the month
var month = epoch.getMonth()+1;
month = zpad(month.toString(), 2);
var year = epoch.getFullYear().toString();
var hour = zpad(epoch.getHours().toString(), 2);
var min = zpad(epoch.getMinutes().toString(), 2);
var sec = zpad(epoch.getSeconds().toString(), 2);

return year + "-" + month + "-" + day + "_" + hour + "-" + min + "-" + sec;
function zpad(str, nb_digits)
{
if (str.length < nb_digits)
{ return (Array(nb_digits - str.length + 1).join('0') + str); }
else
{ return str; }
}
------------------------------------------------------------------

This will take the epoch timestamp instead of the human formatted "photoTakenTime" then convert it - this allows a bit more customisation over the naming format then.

The workflow was along the lines of this:

1. Rename all .mp4 files to .mp4.txt
2. Enable "Pair renaming"
3. Add all .mp4.txt files along with their .json metadata files
4. Run the script above
5. Rename .mp4.txt files back to .mp4

Hope this helps anyone who comes across this.

Cheers,
Phil.


05/09-20 14:49