问题描述
Jekyll支持视频嵌入,包括常用的视频网站的嵌入和使用HTML的方式从本地嵌入视频。
使用视频网站的方式进行的嵌入没有什么问题。
但是在嵌入本地视频的过程中遇到了一些问题。页面里只有一个灰色的播放界面。
我是按照普通的HTML方法进行嵌入:
<video width="100%" controls>
<source src="/assets/video/test_video.mp4" type="video/mp4">
Your browser does not support the video tag.
</video>
解决方案
一开始我认为是文件的权限问题,导致jekyll生成静态网页时没法访问视频文件(理论上只需要拥有读权限即可?)。
使用FTP上传的文件的权限如下:
-rw------- 1 honest ftp_users 11902782 3月 4 09:32 mihomo-linux-amd64-v1.19.3.deb
-rw------- 1 honest ftp_users 3016914 3月 10 16:53 monsta_ftp_2.10.4_install.zip
-rw------- 1 honest ftp_users 230114 3月 11 11:35 sca技术架构.docx
使用chmod修改文件的权限之后问题依然存在。我怀疑是浏览器缓存没有更新导致的改变没有同步(之前也发生过),于是使用Ctrl+Shift+R清除浏览器的缓存。
更奇怪的事情发生了,视频的画面出现了,但是只能播放几秒的视频。
为了更进一步的检查,我使用F12的网络选项查看网页的test_video.mp4的请求的情况。
请求网址:
https://www.honest-zh.me/assets/video/test_video.mp4
请求方法:
GET
状态代码:
304 Not Modified
远程地址:
127.0.0.1:7890
引荐来源网址政策:
strict-origin-when-cross-origin
结果是304 Not Modified,这表示浏览器已经缓存了该视频文件,并且服务器确认缓存仍然有效,因此没有重新下载视频文件。同时注意到网页传输的文件大小和视频实际的大小根本不符合(实际大约160M)。视频文件没有被完整的传输,那应该是设置为流式传输模式的时候出现问题了。
第一个怀疑的是文件的格式问题,素材视频是我使用Nvdia的即时重放功能录制的游戏实况,MP4格式但是我并不清楚他的编码类型。
于是使用ffmpeg检查文件的编码格式。
ffmpeg -i test_video.mp4
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'test_video.mp4':
Metadata:
major_brand : isom
minor_version : 512
compatible_brands: isomiso2avc1mp41
creation_time : 2024-09-07T16:49:50.000000Z
Hw : 1
bitrate : 18000000
maxrate : 0
te_is_reencode : 1
encoder : Lavf58.76.100
Duration: 00:01:30.74, start: 0.000000, bitrate: 14777 kb/s
Stream #0:0[0x1](und): Video: h264 (Main) (avc1 / 0x31637661), yuv420p(tv, bt709, progressive), 1920x1080 [SAR 1:1 DAR 16:9], 14572 kb/s, 60 fps, 60 tbr, 60 tbn (default)
Metadata:
creation_time : 2024-09-07T16:49:50.000000Z
handler_name : VideoHandler
vendor_id : [0][0][0][0]
Stream #0:1[0x2](und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 196 kb/s (default)
Metadata:
creation_time : 2024-09-07T16:49:50.000000Z
handler_name : SoundHandler
vendor_id : [0][0][0][0]
发现是h264 编码,应该是支持流式传输的才对,那么是流式传输哪里的设置错了?流式传输时HTTP请求的状态码应该是206 Partial Content 。
我再使用了curl去查看请求情况:
curl -I https://www.honest-zh.me/assets/video/test_video.mp4
HTTP/1.1 200 OK
Server: nginx/1.24.0 (Ubuntu)
Date: Mon, 17 Mar 2025 03:05:00 GMT
Content-Type: video/mp4
Content-Length: 167619580
Connection: keep-alive
Etag: 7fee5-9fdabfc-67d77e0b
Last-Modified: Mon, 17 Mar 2025 01:42:35 GMT
Cache-Control: private, max-age=0, proxy-revalidate, no-store, no-cache, must-revalidate
发现缺少了应该有的Accept-Ranges: bytes,服务器 未正确配置支持范围请求,导致浏览器无法分段加载视频文件,从而出现灰色播放框。
于是配置Nginx
sudo vi /etc/nginx/sites-available/default
添加以下内容:
# 设置视频的范围请求,进行流式传输
location /assets/video/ {
add_header Accept-Ranges bytes;
}
发现还是存在之前的问题,使用curl的HTTP请求结果竟然变成了404?
思考了一会儿想到的可能的解释是:这是使用的jekyll serve (ruby webrick实现)解析的URL,Nginx不知道它对应的文件是什么!
添加alias让nginx知道对应的系统的路径,完美解决。
# 设置视频的范围请求,进行流式传输
location /assets/video/ {
alias /home/honest/blog/honestblog/assets/video/;
add_header Accept-Ranges bytes;
}
总结:视频文件的权限设置有问题 + 响应头中缺少 Accept-Ranges: bytes(服务器未配置支持范围请求),导致的视频流式传输不正确的问题。