hello. happy Friday or near Friday wherever you are.  Here is a quick component for capturing media in niantic studio. This component can take a screenshot, record video and share. It is straight css; so no extra dependencies. There are likely bugs as I wrote this last night  . Hopefully this is a good starting point for you!
. Hopefully this is a good starting point for you!
import * as ecs from '@8thwall/ecs'
ecs.registerComponent({
  name: 'mediaCapture',
  // schema: {
  // },
  // schemaDefaults: {
  // },
  // data: {
  // },
  add: (world, component) => {
    // create circular button
    const style = document.createElement('style')
    style.textContent = `
  @keyframes pulse {
    0% { transform: scale(1); opacity: 1; }
    50% { transform: scale(1.1); opacity: 0.6; }
    100% { transform: scale(1); opacity: 1; }
  }
  .pulsing {
    animation: pulse 1.2s infinite ease-in-out;
  }
`
    document.head.appendChild(style)
    const wrapper = document.createElement('div')
    wrapper.style.position = 'fixed'
    wrapper.style.bottom = '8rem'
    wrapper.style.left = '50%'
    wrapper.style.transform = 'translateX(-50%)'
    wrapper.style.width = '60px'
    wrapper.style.height = '60px'
    wrapper.style.display = 'flex'
    wrapper.style.justifyContent = 'center'
    wrapper.style.alignItems = 'center'
    wrapper.style.zIndex = '9'
    wrapper.id = 'capture-wrapper'
    // outer ring
    const outerRing = document.createElement('div')
    outerRing.id = 'capture-ring'
    outerRing.style.position = 'absolute'
    outerRing.style.width = '60px'
    outerRing.style.height = '60px'
    outerRing.style.borderRadius = '50%'
    outerRing.style.border = '3px solid white'
    outerRing.style.boxSizing = 'border-box'
    outerRing.style.pointerEvents = 'none'
    wrapper.appendChild(outerRing)
    const btn = document.createElement('button')
    btn.id = 'capture-btn'
    btn.style.width = '52px'
    btn.style.height = '52px'
    btn.style.borderRadius = '50%'
    btn.style.background = '#fff'
    btn.style.border = '2px solid white'
    btn.style.cursor = 'pointer'
    btn.style.outline = 'none'
    wrapper.appendChild(btn)
    document.body.appendChild(wrapper)
    let recording = false
    let pressTimer = null
    const HOLD_THRESHOLD = 300
    const start = () => {
      pressTimer = setTimeout(() => {
        // Long press → start video recording
        if (!recording) {
          console.log('Start recording…')
          world.xr.startMediaRecorder()
          recording = true
          outerRing.classList.add('pulsing')
          btn.style.background = '#ff0000'
        }
      }, HOLD_THRESHOLD)
    }
    const stop = () => {
      clearTimeout(pressTimer)
      if (recording) {
        // End long-press → stop video recording
        console.log('Stop recording…')
        world.xr.stopMediaRecorder()
        recording = false
        outerRing.classList.remove('pulsing')
        btn.style.background = '#fff'
      } else {
        // Short tap → take screenshot
        console.log('Taking screenshot…')
        world.xr.takeScreenshot()
      }
    }
    // mobile touch only
    btn.addEventListener('touchstart', (e) => {
      e.preventDefault()
      start()
    })
    btn.addEventListener('touchend', (e) => {
      e.preventDefault()
      stop()
    })
    btn.addEventListener('touchcancel', (e) => {
      e.preventDefault()
      clearTimeout(pressTimer)
      if (recording) {
        console.log('Stop recording (cancel)…')
        world.xr.stopRecording()
        recording = false
        outerRing.classList.remove('pulsing')
        btn.style.background = '#fff'
      }
    })
    world.events.addListener(world.events.globalId, ecs.events.RECORDER_VIDEO_ERROR, (error) => {
      console.error('Recorder error:', error.message)
    })
    world.events.addListener(
      world.events.globalId,
      ecs.events.RECORDER_SCREENSHOT_READY,
      (e) => {
        console.log('Screenshot ready:', e)
        showPreviewOverlay({type: 'image', blob: e.data})
      }
    )
    world.events.addListener(
      world.events.globalId,
      ecs.events.RECORDER_VIDEO_READY,
      (e) => {
        showPreviewOverlay({type: 'video', blob: e.data.videoBlob})
      }
    )
  },
})
function showPreviewOverlay({type, blob}) {
  const url = URL.createObjectURL(blob)
  const overlay = document.createElement('div')
  overlay.style.position = 'fixed'
  overlay.style.top = '0'
  overlay.style.left = '0'
  overlay.style.width = '100%'
  overlay.style.height = '100%'
  overlay.style.background = 'rgba(0,0,0,0.6)'
  overlay.style.backdropFilter = 'blur(8px)'
  overlay.style.display = 'flex'
  overlay.style.flexDirection = 'column'
  overlay.style.justifyContent = 'center'
  overlay.style.alignItems = 'center'
  overlay.style.zIndex = '1000'
  // Close button
  const closeBtn = document.createElement('button')
  closeBtn.textContent = '✕'
  closeBtn.style.position = 'absolute'
  closeBtn.style.top = '2rem'
  closeBtn.style.right = '2rem'
  closeBtn.style.background = 'rgba(0,0,0,0.5)'
  closeBtn.style.color = 'white'
  closeBtn.style.fontSize = '1.25rem'
  closeBtn.style.border = 'none'
  closeBtn.style.borderRadius = '50%'
  closeBtn.style.width = '40px'
  closeBtn.style.height = '40px'
  closeBtn.style.cursor = 'pointer'
  closeBtn.addEventListener('click', () => overlay.remove())
  overlay.appendChild(closeBtn)
  let file
  if (type === 'video') {
    const vid = document.createElement('video')
    vid.src = url
    vid.autoplay = true
    vid.loop = true
    vid.playsInline = true
    vid.controls = true
    vid.muted = true
    vid.style.width = '230px'
    vid.style.height = 'auto'
    vid.style.borderRadius = '12px'
    vid.style.border = '3px solid white'
    overlay.appendChild(vid)
    file = new File([blob], 'recording.mp4', {type: 'video/mp4'})
  } else if (type === 'image') {
    const img = document.createElement('img')
    img.src = url
    img.style.width = '230px'
    img.style.height = 'auto'
    img.style.borderRadius = '12px'
    img.style.border = '3px solid white'
    overlay.appendChild(img)
    file = new File([blob], 'screenshot.jpg', {type: 'image/jpeg'})
  }
  // share button
  const shareBtn = document.createElement('button')
  shareBtn.textContent = '📤 Share'
  shareBtn.style.position = 'absolute'
  shareBtn.style.bottom = '2rem'
  shareBtn.style.left = '50%'
  shareBtn.style.transform = 'translateX(-50%)'
  shareBtn.style.padding = '0.8rem 2rem'
  shareBtn.style.fontSize = '1rem'
  shareBtn.style.fontWeight = '600'
  shareBtn.style.background = '#e40089'
  shareBtn.style.color = 'white'
  shareBtn.style.border = 'none'
  shareBtn.style.fontFamily = 'Futura'
  shareBtn.style.letterSpacing = '1px'
  shareBtn.style.borderRadius = '9999px'
  shareBtn.style.cursor = 'pointer'
  shareBtn.addEventListener('click', async () => {
    try {
      await navigator.share({files: [file]})
      console.log('Shared successfully')
    } catch (err) {
      console.warn('Share failed:', err)
    }
  })
  overlay.appendChild(shareBtn)
  document.body.appendChild(overlay)
}