Skip to contents

Overview

This quickstart walks through the essential artpipelines workflows with practical examples. By the end, you’ll understand how to:

  1. Validate Procreate canvas files
  2. Upload artwork assets to CDN
  3. Extract metadata and statistics
  4. Run the full processing pipeline

Configuration

Ensure environment variables are set before loading the package:

library(artpipelines)

# Verify database connectivity (via artcore)
artcore::check_env_dba()

# Verify CDN access
artcore::check_env_cdn()

Validating Procreate Canvases

Before processing, validate that a .procreate file contains genuine artwork.

Basic Validation

canvas_path <- "path/to/artwork.procreate"

# Quick check - is this a valid Procreate file?
is_procreate_file(canvas_path)
# [1] TRUE

Detailed Assessment

For comprehensive validation including creative evidence:

result <- assess_procreate_canvas(canvas_path, verbose = TRUE)

# Console output:
# [assess_procreate_canvas] procreate=TRUE | importable=TRUE | creative=definite | class=DEFINITELY_CREATIVE | mp4=12 | tiles=48

# Access individual components
result$is_procreate          # TRUE - valid Procreate structure
result$importable_probable   # TRUE - can likely be opened in Procreate
result$classification        # "DEFINITELY_CREATIVE"

# Evidence details
result$creative_evidence     # "definite"
result$n_mp4_nonempty       # 12 timelapse video segments
result$n_tile_files         # 48 raster tile chunks

Directory Validation

If you’ve already extracted a .procreate file:

# Check an extracted directory
is_procreate_dir("path/to/extracted/canvas/")
# [1] TRUE

Uploading Artwork Assets

The upload functions land files to the appropriate CDN buckets.

Upload Individual Assets

artist <- "746b8207-72f5-4ab6-8d19-a91d03daec3d"
artwork <- "99a61148-1d3b-4340-8cf6-92ad26046b0f"

# Upload main PNG to art-vault
land_artwork_png(artist, artwork, "path/to/main.png")
# Lands to: uploads/{artist}/{artwork}/main.png

# Upload canvas file
land_artwork_raw(artist, artwork, "path/to/canvas.procreate")
# Lands to: uploads/{artist}/{artwork}/canvas.procreate

# Upload timelapse video
land_artwork_mp4(artist, artwork, "path/to/timelapse.mp4")
# Lands to: uploads/{artist}/{artwork}/video.mp4

# Create and upload thumbnail (auto-resized to 350px width)
land_artwork_thumb(artist, artwork, "path/to/main.png")
# Lands to: thumbnails/{artist}/{artwork}.jpeg (art-public bucket)

Upload All Assets at Once

new_utc <- lubridate::now("UTC")

artwork_paths <- upload_artdata(
  artist = artist,
  artwork = artwork,
  new_utc = new_utc,
  file_image = "path/to/main.png",
  file_canvas = "path/to/canvas.procreate",
  file_video = "path/to/timelapse.mp4",
  zip_frames = NULL,
  file_stats = "path/to/stats.png",
  file_variants = NULL
)

# Returns data.table with all CDN paths
artwork_paths$main_png
# [1] "uploads/746b8207-.../99a61148-.../main.png"

artwork_paths$thumbnail
# [1] "thumbnails/746b8207-.../99a61148-....jpeg"

Extracting Metadata

Creation Date from Canvas

# Extract from earliest timelapse segment timestamp
create_date <- extract_create_date(artist, artwork, "path/to/canvas.procreate")
create_date
# [1] "2024-03-15 14:23:17 UTC"

Image Metadata

meta <- extract_image_meta(artist, artwork, "path/to/main.png")

# Basic dimensions and size
meta$meta_1$image_width     # 4096
meta$meta_1$image_height    # 4096
meta$meta_1$image_filesize  # 15234567

# Full EXIF data available in meta_2
meta$meta_2$ColorSpace      # "sRGB"
meta$meta_2$FileModifyDate  # "2024:03:15 14:30:00"

Procreate Statistics

OCR extracts drawing statistics from the stats screenshot:

stats <- extract_stats_procreate(
  artist = artist,
  artwork = artwork,
  fp = "path/to/stats-screenshot.png",
  new_utc = lubridate::now("UTC")
)

stats$drawing_hours   # 12.5
stats$drawing_minutes # 750
stats$brush_strokes   # 45000
stats$n_unique_colors # 1250

Running the Full Pipeline

Combine all steps into a single pipeline run:

result <- run_pipeline(
  artist = "746b8207-72f5-4ab6-8d19-a91d03daec3d",
  artwork = "99a61148-1d3b-4340-8cf6-92ad26046b0f",
  collection = "77102117-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  artist_name = "Bobby Fatemi",
  art_title = "Portrait of Jeezy",
  art_story = "Hip-hop inspired digital portrait",
  file_image = "path/to/main.png",
  file_canvas = "path/to/canvas.procreate",
  file_video = "path/to/timelapse.mp4",
  zip_frames = NULL,
  file_stats = "path/to/stats.png",
  file_variants = NULL
)

# Pipeline executes these steps:
# 1. Validate inputs
# 2. Extract creation date
# 3. Upload all assets to CDN
# 4. Extract artist signature from canvas
# 5. Extract timelapse video segments
# 6. Create gallery images (resized versions)
# 7. Extract timelapse frames
# 8. Create perceptual hash
# 9. Build color dataset from frames
# 10. Create color visualization plots
# 11. Read image metadata
# 12. OCR stats screenshot
# 13. Calculate benchmarks
# 14. Create frame analytics
# 15. Generate AI styles (via artcurator)
# 16. Generate AI profiles (via artcurator)
# 17. Build index record
# 18. Insert all records to database
# 19. Update artist statistics
# 20. Render certificate of authenticity

# Access results
result$artwork_stats$drawing_hours
# [1] 12.5

result$artwork_styles
#>           tag     tag_norm                              desc
#> 1: Digital Art digital_art  Created using digital tools...
#> 2: Portraiture portraiture  Focuses on capturing likeness...

Monitoring Progress

For long-running pipelines, track progress via job management:

# Check currently running pipelines
running <- get_running_pls()
running
#>    job_id   artist_uuid        art_title   status progress
#> 1:  abc123 746b8207-... Portrait of Jeezy Running       45

# Get specific job details
job <- job_get("abc123")
job$msg       # "Building Frame Colors"
job$progress  # 55

Error Handling

Use launch_artwork_pipeline() for production with proper error handling:

tryCatch(
  {
    result <- launch_artwork_pipeline(
      artist = artist,
      artwork = artwork,
      collection = collection,
      # ... other params
    )
  },
  error = function(e) {
    message("Pipeline failed: ", e$message)
    # Job status is automatically updated to "Error"
  }
)

Next Steps