1. 什么是 Live Photos
iPhone6s 和 6s Plus 中增加了一个全新特性—— Live Photos,这新特性的作用是在照片拍摄前后录制一段 1.5 秒的动态视频,当用户在照片上深按一下,照片就会自动播放动态效果。用户还可以将 Live Photos 设置为锁屏墙纸,随时重现动态瞬间。(来自百度百科)
2. 使用方式
在评论时使用如下语法即可:
![图片说明](图片链接)(视频链接)
最终会被渲染成如下 HTML 代码:
<figure>
<div class='livePhotoContainer'
data-live-photo
data-effect-type='live'
data-playback-style='full'
data-proactively-loads-video='true'
data-photo-src='图片链接'
data-video-src='视频链接'></div>
<figcaption>图片说明</figcaption>
</figure>
3. 文章中的效果展示
电脑端请将鼠标光标放在图片左上角的 LIVE
字样上开始播放,光标移出停止。
手机端长按图片开始播放,松开停止。
4. 评论区的使用示例
以下示范步骤均在 Windows 电脑上操作,如果是 Mac 电脑有不同的地方需要大家自己搜索一下解决方案
步骤较多,请耐心观看
- 参照苹果官方文档中不同设备的导出方式将 Live Photo 照片以及对应的视频导出
- 检查导出后图片的编码格式,是否是
JPG
格式,不是的话需要自己搜索一下如何导出为 JPG 格式 - 以宽高比为
3:4
为例(下同),修改图片大小不超过1008 x 1344
- 检查导出后视频的编码格式,如果是
HEVC
或H.265
,需要使用例如ffmpeg
之类的工具将其转为H.264
编码格式 - 修改视频大小不超过
720 x 960
- 将你的图片以及视频上传至一个互联网可访问的地方并提供一个访问链接。且视频的提供方需要支持
206
状态码的分段传输
功能(这个主要是为了兼容 Safari 浏览器) - 在评论区中按照前文中提到的语法输入你的图片以及视频的访问链接即可
4.1. 如何压缩图片
用 windows 自带的图片查看器打开图片,然后鼠标右键选择调整图像大小
:
然后选择定义自定义尺寸
:
勾选保持纵横比
并输入图像的尺寸:
4.2. 如何查看视频的编码方式以及转换编码
以 ffmpeg
工具为例,控制台输入以下命令查看视频的编码信息:
ffprobe 视频路径 -show_streams -select_streams v -print_format json
如果不是 H.264 使用如下命令将其转为 H.264 编码:
ffmpeg -i 转换前的视频 -c:v libx264 -crf 23 -preset medium -c:a aac -b:a 128k 转换后的视频
4.3. 如何压缩视频到指定大小
依旧以 ffmpeg 为例,将视频压缩到 720 x 960
,使用如下命令:
ffmpeg -i 转换前的视频 -vf scale=720:960 转换后的视频 -hide_banner
4.4. 评论区中的展示效果
5. 注意事项
图片说明
不是必填项,即使不填的话那一对中括号也不能少图片链接
是你的 Live Photo 导出后的后缀为.JPG
的图片的访问链接,如果是HEIC
格式的话需要自己处理一下导出为JPG
格式才行视频链接
是你的 Live Photo 导出后的后缀为.MOV
的视频的访问链接- 重点 1:宽高比为
3:4
比例的图片大小请勿超过1088 x 1344
,其他宽高比暂时没测试过,但越小越好,因为官方的实现原理原因,太大了会导致 safari 浏览器体验效果极差 - 重点 2:视频格式必须是
.MOV
格式(不区分大小写),且返回的数据的响应头必须为video/quicktime
,且宽高比为3:4
的视频的大小请勿超过720 x 960
,理由同上 - 重点 3:视频编码方式需要是
H.264
,如果导出来的是HEVC
编码的,很多浏览器都不兼容这个编码的视频播放,需要自己转换一下 - 重点 4:存在一定概率连续播放几次后就没法播放了,这个没法解决,只有刷新页面解决
- 重点 5:这个功能的兼容性不是很好,Google、Safari 这些是没有问题的(版本过低也不行),其他浏览器以及一些应用内置的浏览器可能无法查看,所以如果你无法查看请切换浏览器试试
6. 实现原理
- Live Photo 的展示实现是参考苹果官方的LivePhotosKit JS 文档
- 网站的 Live Photo 图片展示的 Markdown 语法是按照 Marked 官方的 Marked Documentation 来自定义的
扩展代码:
const caret = /(^|[^\[])\^/g
const _label = /(?:\[(?:\\.|[^\[\]\\])*\]|\\.|`[^`]*`|[^\[\]\\`])*?/
const _href = /<(?:\\.|[^\n<>\\])+>|[^\s\x00-\x1f]*/
function edit(regex, opt) {
regex = typeof regex === 'string' ? regex : regex.source
opt = opt || ''
const obj = {
replace: (name, val) => {
val = val.source || val
val = val.replace(caret, '$1')
regex = regex.replace(name, val)
return obj
},
getRegex: () => {
return new RegExp(regex, opt)
}
}
return obj
}
const livePhoto = {
name: 'livePhoto',
level: 'block',
start(src) {
return src.match(/![^!\n]/)?.index
},
tokenizer(src, tokens) {
let rule = /^!?\[(label)\]\(\s*(photoSrc)?\s*\)\(\s*(videoSrc)?\s*\)/
rule = edit(rule)
.replace('label', _label)
.replace('photoSrc', _href)
.replace('videoSrc', _href)
.getRegex()
const match = rule.exec(src)
if (match) {
const token = {
type: 'livePhoto',
raw: match[0],
text: match[0].trim(),
label: match[1],
photoSrc: match[2],
videoSrc: match[3],
tokens: []
}
this.lexer.inline(token.text, token.tokens)
return token
}
},
renderer(token) {
return `
<figure>
<div class='livePhotoContainer'
data-live-photo
data-effect-type='live'
data-playback-style='full'
data-proactively-loads-video='true'
data-photo-src='${token.photoSrc}'
data-video-src='${token.videoSrc}'></div>
<figcaption>${token.label}</figcaption>
</figure>
`
}
}
marked.use({extensions: [livePhoto]})
13 条评论
这个好牛,关注你的博客了!
嘿嘿,谢谢夸奖~其实这个就是根据官方文档一步一步实现的,只是兼容性问题导致踩了很多坑。
您好,看你的站做的挺不错的,有没有出手的打算,想出手的话,联系QQ2605765954。
cooool。周末折腾看看👀
期待~
感觉好复杂,我挺想搞,但感觉搞不定
加油,相信自己可以的!!
其实只是实现功能的话关官方文档上有现成的 demo,需要折腾的点在于处理兼容性问题需要折腾很多(其实主要还是踩坑解决问题花比较多时间,我感觉我应该是已经把坑都踩完了,所以注意一下我踩过的坑应该问题不大)。
还有就是官方的 demo 是没法自适应大小的,当屏幕大小变化时样式会很难看。自适应大小这块儿我也做了很多细节的处理,不过这个属于样式的范畴了,慢慢优化即可,对功能影响不大。
自定义 markdown 语法纯属是为了自己写文章偷懒以及方便访客使用(虽然还从来没有访客用过这个功能)也是可以不需要的,完全可以自己写 html。
嗯,暂时还用不上这个,
这个好哎
是的。不过就是兼容性确实太差了。
66666