File organization

The first step in the MAMMals workflow is to extract the metadata of all multimedia files. For example, files can be organized into separate subfolders in the root directory:

#> /Volumes/mydisk/MAMMals
#> ├── export_data
#> ├── export_media
#> ├── flightlogs
#> ├── photoid
#> ├── photoid.csv
#> ├── photoid.txt
#> └── videos

A good practice is to set the input and output folder paths to the folders of raw and processed multimedia data. For example, we can set the folder path a priori for our photo-identification data, drone video files and flight logs as:

photo_folderpath =  '/Volumes/mydisk/MAMMals/photoid'
video_folderpath = '/Volumes/mydisk/MAMMals/videos'
flight_folderpath = '/Volumes/mydisk/MAMMals/flightlogs'

Is is also convenient to create new folders to store the outputs:

if(isFALSE(dir.exists('/Volumes/AMSM/20210202_test/export_media')))
  dir.create('/Volumes/mydisk/MAMMals/export_media')
#> Warning in dir.create("/Volumes/mydisk/MAMMals/export_media"): '/Volumes/mydisk/
#> MAMMals/export_media' já existe

if(isFALSE(dir.exists('/Volumes/mydisk/MAMMals/export_data')))
  dir.create('/Volumes/mydisk/MAMMals/export_data')

export_file_folder <- '/Volumes/mydisk/MAMMals/export_media'
export_data_folder <- '/Volumes/mydisk/MAMMals/export_data'

Extract metadata of photo-identification data

To extract the metadata of all images in the subfolder photoid, use the function getPhotoMetadata(). Use the argument extension to set the image file extensions to look for in the photo_folderpath and set the timezone accordingly to where the photos were taken.

photos_metadata <- MAMMals::getPhotoMetadata(
  ROOTfolderpath = photo_folderpath, 
  extension = '.jpg', 
  ignore = NULL, 
  timezone = "America/Sao_Paulo", 
  export = NULL,
  data_photoid = NULL
)

The metadata of all .jpg images in the photo_folderpath will be stored in the data frame photos_metadata:

str(photos_metadata)
#> Classes 'photo-id' and 'data.frame': 19 obs. of  21 variables:
#>  $ camera.photo_path         : chr  "/Volumes/mydisk/MAMMals/photoid" "/Volumes/mydisk/MAMMals/photoid" "/Volumes/mydisk/MAMMals/photoid" "/Volumes/mydisk/MAMMals/photoid" ...
#>  $ camera.photo_filename     : chr  "6Q1A0177.JPG" "6Q1A0178.JPG" "6Q1A0179.JPG" "6Q1A0180.JPG" ...
#>  $ camera.PHOTOID            : logi  NA NA NA NA NA NA ...
#>  $ camera.photo_filename_exif: chr  "6Q1A0177.JPG" "6Q1A0178.JPG" "6Q1A0179.JPG" "6Q1A0180.JPG" ...
#>  $ camera.datetime_GPS_UTC   : chr  "2019-05-22 15:05:14" "2019-05-22 15:05:14" "2019-05-22 15:05:29" "2019-05-22 15:05:59" ...
#>  $ camera.datetime_local     : chr  "2019-05-22 12:05:15" "2019-05-22 12:05:15" "2019-05-22 12:05:30" "2019-05-22 12:06:01" ...
#>  $ camera.CreateDate         : chr  "2019-05-22 12:05:15" "2019-05-22 12:05:15" "2019-05-22 12:05:30" "2019-05-22 12:06:01" ...
#>  $ camera.TimeZone           : chr  "-03:00" "-03:00" "-03:00" "-03:00" ...
#>  $ camera.TimeZoneCity       : chr  "Sao Paulo" "Sao Paulo" "Sao Paulo" "Sao Paulo" ...
#>  $ camera.DaylightSavings    : chr  "Off" "Off" "Off" "Off" ...
#>  $ camera.CanonModelID       : chr  "EOS 7D Mark II" "EOS 7D Mark II" "EOS 7D Mark II" "EOS 7D Mark II" ...
#>  $ camera.GPSLatitudeRef     : chr  "South" "South" "South" "South" ...
#>  $ camera.GPSLongitudeRef    : chr  "West" "West" "West" "West" ...
#>  $ camera.GPSMapDatum        : chr  "WGS-84" "WGS-84" "WGS-84" "WGS-84" ...
#>  $ camera.GPSAltitude        : chr  "3.9 m Above Sea Level" "3.9 m Above Sea Level" "3.5 m Above Sea Level" "1.1 m Below Sea Level" ...
#>  $ camera.direction.angle    : chr  "226" "226" "167" "241" ...
#>  $ camera.direction.angle.ref: chr  "Magnetic North" "Magnetic North" "Magnetic North" "Magnetic North" ...
#>  $ camera.GPSLatitude        : chr  "28 deg 29' 44.91\" S" "28 deg 29' 44.91\" S" "28 deg 29' 44.87\" S" "28 deg 29' 44.77\" S" ...
#>  $ camera.GPSLongitude       : chr  "48 deg 45' 35.74\" W" "48 deg 45' 35.74\" W" "48 deg 45' 35.69\" W" "48 deg 45' 35.74\" W" ...
#>  $ camera.latitude           : num  -28.5 -28.5 -28.5 -28.5 -28.5 ...
#>  $ camera.longitude          : num  -48.8 -48.8 -48.8 -48.8 -48.8 ...

Assign individual identification

If photo-identification data is available, it can be assigned directly into the data.frame photos_metadata. To do that, select only the columns with image file name and the respective ID for each photo. Images with no individual ID can be ignored in the getPhotoMetadata() passing a character vector to the argument ignore.

# read photo id data
photoid <- utils::read.csv(file = "/Volumes/mydisk/MAMMals/photoid.csv")

head(photoid)
#>            camera.photo_path camera.photo_filename camera.PHOTOID
#> 1 F:/fotoidrone_test/photoid          6Q1A0177.JPG           L_24
#> 2 F:/fotoidrone_test/photoid          6Q1A0178.JPG           L_24
#> 3 F:/fotoidrone_test/photoid          6Q1A0179.JPG           L_24
#> 4 F:/fotoidrone_test/photoid          6Q1A0180.JPG           L_26
#> 5 F:/fotoidrone_test/photoid          6Q1A0181.JPG           L_26
#> 6 F:/fotoidrone_test/photoid          6Q1A0182.JPG           L_26
#>   camera.photo_filename_exif camera.datetime_GPS_UTC camera.datetime_local
#> 1               6Q1A0177.JPG     2019-05-22 15:05:14   2019-05-22 12:05:15
#> 2               6Q1A0178.JPG     2019-05-22 15:05:14   2019-05-22 12:05:15
#> 3               6Q1A0179.JPG     2019-05-22 15:05:29   2019-05-22 12:05:30
#> 4               6Q1A0180.JPG     2019-05-22 15:05:59   2019-05-22 12:06:01
#> 5               6Q1A0181.JPG     2019-05-22 15:06:14   2019-05-22 12:06:29
#> 6               6Q1A0182.JPG     2019-05-22 15:06:14   2019-05-22 12:06:29
#>     camera.CreateDate camera.TimeZone camera.TimeZoneCity
#> 1 2019-05-22 12:05:15          -03:00           Sao Paulo
#> 2 2019-05-22 12:05:15          -03:00           Sao Paulo
#> 3 2019-05-22 12:05:30          -03:00           Sao Paulo
#> 4 2019-05-22 12:06:01          -03:00           Sao Paulo
#> 5 2019-05-22 12:06:29          -03:00           Sao Paulo
#> 6 2019-05-22 12:06:29          -03:00           Sao Paulo
#>   camera.DaylightSavings camera.CanonModelID camera.GPSLatitudeRef
#> 1                    Off      EOS 7D Mark II                 South
#> 2                    Off      EOS 7D Mark II                 South
#> 3                    Off      EOS 7D Mark II                 South
#> 4                    Off      EOS 7D Mark II                 South
#> 5                    Off      EOS 7D Mark II                 South
#> 6                    Off      EOS 7D Mark II                 South
#>   camera.GPSLongitudeRef camera.GPSMapDatum    camera.GPSAltitude
#> 1                   West             WGS-84 3.9 m Above Sea Level
#> 2                   West             WGS-84 3.9 m Above Sea Level
#> 3                   West             WGS-84 3.5 m Above Sea Level
#> 4                   West             WGS-84 1.1 m Below Sea Level
#> 5                   West             WGS-84 3.6 m Below Sea Level
#> 6                   West             WGS-84 3.6 m Below Sea Level
#>   camera.direction.angle camera.direction.angle.ref
#> 1                    226             Magnetic North
#> 2                    226             Magnetic North
#> 3                    167             Magnetic North
#> 4                    241             Magnetic North
#> 5                    247             Magnetic North
#> 6                    246             Magnetic North
#>                          camera.GPSLatitude camera.GPSLongitude camera.latitude
#> 1 28 deg 29' 44.91\\ S,48 deg 45' 35.74\\ W           -28.49581       -48.75993
#> 2 28 deg 29' 44.91\\ S,48 deg 45' 35.74\\ W           -28.49581       -48.75993
#> 3 28 deg 29' 44.87\\ S,48 deg 45' 35.69\\ W           -28.49580       -48.75991
#> 4 28 deg 29' 44.77\\ S,48 deg 45' 35.74\\ W           -28.49577       -48.75993
#> 5 28 deg 29' 44.77\\ S,48 deg 45' 35.72\\ W           -28.49577       -48.75992
#> 6 28 deg 29' 44.77\\ S,48 deg 45' 35.72\\ W           -28.49577       -48.75992
#>   camera.longitude
#> 1               NA
#> 2               NA
#> 3               NA
#> 4               NA
#> 5               NA
#> 6               NA
# check photos with no individual identification
ignore.photos <- photoid[is.na(photoid$camera.PHOTOID), 'camera.photo_filename']

# extract metadata, ignore photos with no ID, export .csv file and assign photoid to data_photoid
photos_metadata <- MAMMals::getPhotoMetadata(
  ROOTfolderpath = photo_folderpath, 
  extension = '.jpg', 
  ignore = ignore.photos, 
  timezone = "America/Sao_Paulo", 
  export = paste0(export_data_folder, "/photoid_metadata.csv"),
  data_photoid = photoid[, c("camera.photo_filename","camera.PHOTOID")]
)
# check data
head(photos_metadata)
#>                 camera.photo_path camera.photo_filename camera.PHOTOID
#> 1 /Volumes/mydisk/MAMMals/photoid          6Q1A0177.JPG           L_24
#> 2 /Volumes/mydisk/MAMMals/photoid          6Q1A0178.JPG           L_24
#> 3 /Volumes/mydisk/MAMMals/photoid          6Q1A0179.JPG           L_24
#> 4 /Volumes/mydisk/MAMMals/photoid          6Q1A0180.JPG           L_26
#> 5 /Volumes/mydisk/MAMMals/photoid          6Q1A0181.JPG           L_26
#> 6 /Volumes/mydisk/MAMMals/photoid          6Q1A0182.JPG           L_26
#>   camera.photo_filename_exif camera.datetime_GPS_UTC camera.datetime_local
#> 1               6Q1A0177.JPG     2019-05-22 15:05:14   2019-05-22 12:05:15
#> 2               6Q1A0178.JPG     2019-05-22 15:05:14   2019-05-22 12:05:15
#> 3               6Q1A0179.JPG     2019-05-22 15:05:29   2019-05-22 12:05:30
#> 4               6Q1A0180.JPG     2019-05-22 15:05:59   2019-05-22 12:06:01
#> 5               6Q1A0181.JPG     2019-05-22 15:06:14   2019-05-22 12:06:29
#> 6               6Q1A0182.JPG     2019-05-22 15:06:14   2019-05-22 12:06:29
#>     camera.CreateDate camera.TimeZone camera.TimeZoneCity
#> 1 2019-05-22 12:05:15          -03:00           Sao Paulo
#> 2 2019-05-22 12:05:15          -03:00           Sao Paulo
#> 3 2019-05-22 12:05:30          -03:00           Sao Paulo
#> 4 2019-05-22 12:06:01          -03:00           Sao Paulo
#> 5 2019-05-22 12:06:29          -03:00           Sao Paulo
#> 6 2019-05-22 12:06:29          -03:00           Sao Paulo
#>   camera.DaylightSavings camera.CanonModelID camera.GPSLatitudeRef
#> 1                    Off      EOS 7D Mark II                 South
#> 2                    Off      EOS 7D Mark II                 South
#> 3                    Off      EOS 7D Mark II                 South
#> 4                    Off      EOS 7D Mark II                 South
#> 5                    Off      EOS 7D Mark II                 South
#> 6                    Off      EOS 7D Mark II                 South
#>   camera.GPSLongitudeRef camera.GPSMapDatum    camera.GPSAltitude
#> 1                   West             WGS-84 3.9 m Above Sea Level
#> 2                   West             WGS-84 3.9 m Above Sea Level
#> 3                   West             WGS-84 3.5 m Above Sea Level
#> 4                   West             WGS-84 1.1 m Below Sea Level
#> 5                   West             WGS-84 3.6 m Below Sea Level
#> 6                   West             WGS-84 3.6 m Below Sea Level
#>   camera.direction.angle camera.direction.angle.ref  camera.GPSLatitude
#> 1                    226             Magnetic North 28 deg 29' 44.91" S
#> 2                    226             Magnetic North 28 deg 29' 44.91" S
#> 3                    167             Magnetic North 28 deg 29' 44.87" S
#> 4                    241             Magnetic North 28 deg 29' 44.77" S
#> 5                    247             Magnetic North 28 deg 29' 44.77" S
#> 6                    246             Magnetic North 28 deg 29' 44.77" S
#>   camera.GPSLongitude camera.latitude camera.longitude
#> 1 48 deg 45' 35.74" W       -28.49581        -48.75993
#> 2 48 deg 45' 35.74" W       -28.49581        -48.75993
#> 3 48 deg 45' 35.69" W       -28.49580        -48.75991
#> 4 48 deg 45' 35.74" W       -28.49577        -48.75993
#> 5 48 deg 45' 35.72" W       -28.49577        -48.75992
#> 6 48 deg 45' 35.72" W       -28.49577        -48.75992

Extract metadata of multimedia data

To extract the metadata of videos and audios, use the getVideoMetadata() in the video_folderpath or the getAudioMetadata() in the audio_folderpath. For example, use the getVideoMetadata() to read the metadata of drone video files. If video subtitles (.SRT files) are available, use the argument include_srt_datetime to include the time from the subtitles.

videos_metadata <- MAMMals::getVideoMetadata(
  ROOTfolderpath = video_folderpath,
  extension = '.mp4', 
  include_srt_datetime = FALSE,
  ignore = NULL, 
  timezone = "America/Sao_Paulo",  
  export = paste0(export_data_folder, "/video_metadata.csv")
  )
# check data
head(videos_metadata)
#>                     video.folder video.filename
#> 1 /Volumes/mydisk/MAMMals/videos   DJI_0042.MP4
#> 2 /Volumes/mydisk/MAMMals/videos   DJI_0044.MP4
#> 3 /Volumes/mydisk/MAMMals/videos   DJI_0045.MP4
#>                                    video.path video.local_start_datetime
#> 1 /Volumes/mydisk/MAMMals/videos/DJI_0042.MP4        2019-05-22 11:59:05
#> 2 /Volumes/mydisk/MAMMals/videos/DJI_0044.MP4        2019-05-22 12:20:43
#> 3 /Volumes/mydisk/MAMMals/videos/DJI_0045.MP4        2019-05-22 12:58:50
#>   video.duration video.local_end_datetime
#> 1    00:15:43.72      2019-05-22 12:14:48
#> 2    00:20:28.24      2019-05-22 12:41:11
#> 3    00:21:00.03      2019-05-22 13:19:50