Takeout JSON

Corrigir datas do Google Takeout com exiftool: o guia honesto

O comando do exiftool que copia datas e GPS dos .json do Takeout para as fotos, onde ele falha, e quando vale parar e usar um programa com janela.

O exiftool é gratuito, roda em qualquer sistema e consegue corrigir uma exportação do Google Takeout. A maioria dos tutoriais dá um comando e para por aí. Esse comando funciona em mais ou menos quatro fotos a cada cinco. Este guia conta o que acontece com a quinta.

Instalação

No Mac, brew install exiftool. No Debian ou Ubuntu, sudo apt install libimage-exiftool-perl. No Fedora, sudo dnf install perl-Image-ExifTool. No Windows, baixe o zip em exiftool.org, descompacte e renomeie exiftool(-k).exe para exiftool.exe. Depois abra um terminal na pasta que contém a pasta Takeout descompactada.

Trabalhe em uma cópia na primeira vez. O exiftool grava dentro dos seus arquivos.

O comando

Cada foto tem um JSON ao lado: IMG_2034.JPG.supplemental-metadata.json nas exportações de 2024 em diante, IMG_2034.JPG.json nas mais antigas. O photoTakenTime.timestamp do JSON é a data real, em segundos desde 1970. Isto copia a data para dentro da foto:

exiftool -r -d %s -tagsfromfile "%d/%F.supplemental-metadata.json" \
  "-DateTimeOriginal<PhotoTakenTimeTimestamp" \
  "-CreateDate<PhotoTakenTimeTimestamp" \
  "-FileModifyDate<PhotoTakenTimeTimestamp" \
  -ext jpg -ext jpeg -ext png -ext heic -ext gif \
  -overwrite_original -progress "Takeout/Google Fotos"

Parte por parte: -r percorre as subpastas. -d %s avisa o exiftool que a data que ele lê é um número de época. -tagsfromfile monta o nome do JSON com %d (a pasta da foto) e %F (o nome do arquivo com extensão). As três linhas com < copiam o timestamp para a data EXIF, para a data de criação EXIF e para a data de modificação do arquivo. -overwrite_original impede o exiftool de deixar uma cópia _original de cada arquivo.

Se a pasta da sua exportação se chama Google Photos em vez de Google Fotos, ajuste o caminho. O nome depende do idioma da conta.

Para uma exportação antiga, rode de novo com "%d/%F.json". Arquivos que já receberam data na primeira passada são simplesmente regravados com o mesmo valor.

Para acrescentar o GPS na mesma passada, adicione quatro linhas:

  "-GPSLatitude<GeoDataLatitude" "-GPSLatitudeRef<GeoDataLatitude" \
  "-GPSLongitude<GeoDataLongitude" "-GPSLongitudeRef<GeoDataLongitude" \

O Google grava 0.0 para fotos sem localização, então envolva isso em -if '$GeoDataLatitude ne 0' ou você vai colocar algumas centenas de fotos no meio do Atlântico. Há mais sobre isso em fotos do Takeout sem localização.

Quando termina, o exiftool imprime quantos arquivos atualizou e quantos pulou. Os pulados são onde a noite vai embora.

Onde ele falha

Nomes de JSON cortados. O Google corta nomes longos de JSON em cerca de 46 caracteres. PXL_20230812_193044123.RAW-01.COVER.jpg ganha um JSON chamado PXL_20230812_193044123.RAW-01.COVER.supplemen.json ou mais curto. O padrão %F nunca bate. Nomes longos de câmera, nomes do WhatsApp e qualquer coisa com uma descrição no nome caem nisso. Você precisa listar o que sobrou e combinar na mão ou com um script.

Duplicatas com (1). Se você enviou o mesmo nome duas vezes, a foto é IMG_1234(1).jpg mas o JSON é IMG_1234.jpg(1).json. O parêntese mudou de lugar. Uma passada de renomeação nos JSON corrige isso antes de rodar o comando principal:

for j in "Takeout/Google Fotos"/*/*"("*").json"; do
  mv "$j" "$(echo "$j" | sed -E 's/\.([a-zA-Z0-9]+)\(([0-9]+)\)(\.supplemental-metadata)?\.json$/(\2).\1\3.json/')"
done

Cópias editadas. IMG_1234-edited.jpg não tem JSON próprio. Ela compartilha o do original. Depois que os originais estiverem prontos, copie a partir deles:

for f in "Takeout/Google Fotos"/*/*-edited.*; do
  exiftool -tagsfromfile "${f/-edited/}" -AllDates -GPS:all -overwrite_original "$f"
done

Vídeos. Arquivos MP4 e MOV não usam EXIF. Eles guardam as datas no container QuickTime, em tags diferentes, e essas tags são lidas como UTC:

exiftool -r -d %s -api QuickTimeUTC -tagsfromfile "%d/%F.supplemental-metadata.json" \
  "-CreateDate<PhotoTakenTimeTimestamp" "-ModifyDate<PhotoTakenTimeTimestamp" \
  "-TrackCreateDate<PhotoTakenTimeTimestamp" "-MediaCreateDate<PhotoTakenTimeTimestamp" \
  "-FileModifyDate<PhotoTakenTimeTimestamp" \
  -ext mp4 -ext mov -overwrite_original "Takeout/Google Fotos"

Clipes de Live Photo não têm JSON nenhum, então continuam sem data depois disso. O artigo sobre pares de Live Photo (em inglês) tem um laço para eles.

A armadilha do fuso horário

O timestamp do JSON é um instante exato em UTC. O DateTimeOriginal do EXIF é uma hora de relógio de parede, sem fuso. O exiftool faz a ponte usando o fuso atual do seu computador. Uma foto tirada às 11h05 em São Paulo sai como 11h05 se a máquina está em horário de Brasília e como 16h05 se está em horário de Lisboa.

Defina o fuso antes de rodar, para o lugar onde a maioria das fotos foi tirada:

TZ=America/Sao_Paulo exiftool ...

Fotos de viagem em outros fusos ainda vão sair com algumas horas de diferença. Não há como contornar isso só com o JSON; o EXIF da própria câmera, se sobreviveu, é o único registro da hora local. Não "corrija" fotos que já têm uma data EXIF boa. Acrescente -if 'not $DateTimeOriginal' para deixá-las em paz.

A noite vale a pena?

Para uma exportação limpa de alguns milhares de fotos de câmera, o exiftool leva uma hora, contando a leitura deste guia. Reserve uma noite para uma biblioteca real, com imagens de WhatsApp, prints, duplicatas (1), HEIC, vídeos e Live Photos, e espere rodar exiftool -r -if 'not $DateTimeOriginal' -filename algumas vezes para ver o que ainda está sem data.

Se você também quer os arquivos renomeados por data, organizados em pastas de ano e mês, HEIC convertido para JPG e pares de Live Photo mantidos juntos, são mais quatro comandos e um laço. Tudo bem se você gosta disso. O GooglePhotosTakeoutHelper é um script gratuito que cuida das manias de nome para você, e é um bom meio-termo se você se vira no terminal mas não quer escrever o sed sozinho.

O aplicativo

O Takeout JSON Metadata Fixer faz a lista inteira em uma execução, com simulação antes, no macOS, no Windows e no Linux.

Ele combina cada foto com o seu JSON, incluindo os nomes cortados, as duplicatas (1) e as cópias -edited, e grava o photoTakenTime e o GPS no arquivo. Vídeos recebem as tags QuickTime. Clipes de Live Photo herdam a data da foto. Fotos sem JSON mantêm a data EXIF, e fotos sem nenhum dos dois recebem a data do arquivo, então nenhuma sai sem data.

Modelos de nome e de pasta são opcionais; "Manter nomes" e "Manter minhas pastas" faz só as datas. Ele confere o espaço em disco antes de começar e roda inteiramente offline. As primeiras 1000 fotos são grátis. Ilimitado custa US$ 19,99 uma vez, que é menos do que uma noite.

Perguntas frequentes

O exiftool diz "Warning: No writable tags set from" um JSON. O que significa?

O JSON existe mas não tem photoTakenTime, ou o padrão de nome bateu com o arquivo errado. Abra o .json e confira. Os metadata.json de álbum disparam esse aviso também e podem ser ignorados.

Posso rodar nos zips sem descompactar?

Não. O exiftool precisa dos arquivos no disco. Descompacte todas as partes em uma pasta primeiro, como descrito em Google Takeout dividido em vários arquivos zip.

Gravar EXIF altera a imagem?

Não. O exiftool regrava o bloco de metadados e não toca nos dados da imagem. O arquivo pode crescer algumas centenas de bytes.

Qual data devo copiar, photoTakenTime ou creationTime?

photoTakenTime. creationTime é quando o arquivo foi enviado para o Google, o que muitas vezes é anos depois.