拆解iOS实况照片📷 - 附React web实现

前言

我认为苹果的实况照片(live photo)是一个伟大的发明,可以让你的回忆变得鲜活起来。前几天想在我的web项目中还原苹果系统里实况照片的效果,发现网络上相关的教程很少,于是我在调研实现之后,想和大家分享一下。

技术实现

文件格式

实况照片其实并不是一个什么神奇的魔法图片格式,它仅仅是一个"图片+视频的组合包 "。你在iPhone上拍摄一个实况照片,它会存储一个HEIC或者JPG图片、再存储一个3秒左右的MOV视频。iOS相册中查看图片,静态显示图片,长按播放视频,就是所谓的实况照片了。

iOS相关设置

  • 选择实况照片"图片部分"的格式:在iphone设置 -> 相机 -> 格式 -> 相机拍摄

    • 选择"高效"(默认):图片存储为HEIF格式,保证画质无损情况下可以压缩更多空间。但是浏览器默认不支持显示HEIF格式的图片(见PS部分)
    • 选择"兼容性最佳":图片存储为更传统的JPEG格式
  • 分享完整实况照片:iOS相册 -> 选择一个实况照片 -> 分享 -> 选项 -> 启用"所有照片数据"

    • 这样分享给你的电脑,你会发现电脑里是一个文件夹,里面包含了一张图片和一段MOV视频

web实现

想在web中实现实况照片效果,苹果官方提供了一个工具库(LivePhotosKit JS)

这个库提供了一个Player,你可以使用react的useRef,将对应div的Ref传入这个Player,让你的组件受player的控制。你可以通过player设置图片部分资源、视频部分资源、控制播放与暂停。

React代码

  • LivePhotoPlayer.tsx 实现了实况照片的展示,支持长按播放、松开回弹
tsx 复制代码
import React, { useEffect, useRef, useCallback } from 'react'
import * as LivePhotosKitNS from 'livephotoskit'

const LivePhotosKit: typeof LivePhotosKitNS =
  (LivePhotosKitNS as any).default ?? LivePhotosKitNS

type LivePhotoPlayerProps = {
  photoUrl: string
  videoUrl: string
  style?: React.CSSProperties
}

export const LivePhotoPlayer = ({
  photoUrl,
  videoUrl,
  style,
}: LivePhotoPlayerProps) => {
  const containerRef = useRef<HTMLDivElement>(null)
  const playerRef = useRef<any>(null)
  const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null)

  useEffect(() => {       //初始化player
    if (!containerRef.current) return
    const player = LivePhotosKit.Player(containerRef.current)
    player.photoSrc = photoUrl
    player.videoSrc = videoUrl
    player.showsNativeControls = true //显示一个icon控件
    player.playbackStyle = LivePhotosKit.PlaybackStyle.FULL
    playerRef.current = player
  }, [])

  const handlePointerDown = useCallback(() => {   //长按播放
    timerRef.current = setTimeout(() => {
      playerRef.current?.play()
    }, 200)
  }, [])

  const handlePointerUp = useCallback(() => {      //松开暂停
    if (timerRef.current) clearTimeout(timerRef.current)
    playerRef.current?.stop()
  }, [])

  return (
    <div
      ref={containerRef}
      style={style}
      className="cursor-pointer"
      onPointerDown={handlePointerDown}
      onPointerUp={handlePointerUp}
      onPointerLeave={handlePointerUp}
    />
  )
}

PS

为什么浏览器不支持HEIF?

  1. 专利费: HEIF 核心的 HEVC 编码涉及昂贵的专利授权费用。

  2. 算力要求: 解码 HEIF 比解码 JPEG 更消耗 CPU/GPU 资源。

  3. 竞争对手: Google 等巨头正在推广 WebP 和 AVIF ,后者同样高效且完全开源免费。

    苹果之所以选择 HEIC,是因为自 A10 芯片起,iPhone 硬件层面就集成了 HEVC 编解码器,拍照和查看时几乎不耗电,且能省下一半的手机空间。

  • 如果想在web上支持HEIF格式,需要使用一些库来转换,如libheif、heic2any ,本文不作介绍了。
相关推荐
geovindu7 小时前
css: Timeline scribble
前端·css·iphone
沙漠之主15 小时前
C++编程教学设计资料:从入门到实战的完整课程方案
java·前端·c++
hasty15 小时前
不上传新包,也能改变用户拿到的版本:npm dist-tag 的 OIDC 权限治理
前端·npm·node.js
Csvn15 小时前
diff 算法(虚拟 DOM Reconciliation)
前端
前端snow16 小时前
ai agent --- 文件存储
前端
Frag0ut16 小时前
Chrome四大版本获取及共存指南:Stable/Beta/Dev/Canary
前端·chrome·浏览器·dev·beta·canary·共存版
IT_陈寒18 小时前
SpringBoot自动配置坑了我一把,原来是这样绕过去的
前端·人工智能·后端
广州华水科技18 小时前
单北斗GNSS变形监测在大坝安全监测中的应用与优势
前端
zeng不错18 小时前
B站 173 个投稿活动看到眼瞎?我写了个扩展,主打一个精准打击
前端
Latchh18 小时前
前端导出的JPEG红字发糊,质量要拉到100才清楚
前端·图像处理·人工智能·计算机视觉