Ruby on Rails ActiveStorage仅显示视频首帧(206 Partial Content)
问题描述
当前行为
访问应用的/video页面时,仅显示视频第一帧,控制台输出Partial Content的GET请求,但无后续播放操作。
代码检视
视频页面HTML代码
<video autoplay=true type="video/mp4" src="<%=@redirectURL%>"/>
Rails控制器代码
class VideoController < ApplicationController def index ActiveStorage::Current.url_options = "http://127.0.0.1:3000" if session[:user_id] @user = User.find(session[:user_id]) @redirectURL = url_for(@user.video) end end end
注册页面HTML代码
<h1>Sign up</h1> <%= form_with model: @user, url: signup_path do |form|%> <% if @user.errors.any? %> <div class="alert alert-danger"> <% @user.errors.full_messages.each do |message| %> <div> <%= message %></div> <% end %> <% end %> <div class="mb-3"> <%= form.label :email %> <%= form.text_field :email, class: "form-control", placeholder: "example@site.com"%> </div> <div class="mb-3"> <%= form.label :password %> <%= form.password_field :password, class: "form-control", placeholder: "secretpassword123" %> </div> <div class="mb-3"> <%= form.label :password_confirmation %> <%= form.password_field :password_confirmation, class: "form-control", placeholder: "secretpassword123" %> </div> <div class="input-group mb-3"> <%= form.label :video, class: "input-group-text", for: "inputGroupFile01"%> <%= form.file_field :video, class: "form-control", id: "inputGroupFile01" %> </div> <div class="mb-3"> <%= form.submit "Get Started!" , class: "btn btn-primary" %> </div> <% end %>
服务器日志
重定向请求日志
Started GET "/rails/active_storage/blobs/redirect/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBCdz09IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--77812323ea618480d0497c73b1b1cb96856a585a/048496124_main_xxl.mp4" for 127.0.0.1 at 2023-05-04 23:24:24 -0400 Processing by ActiveStorage::Blobs::RedirectController#show as MP4 Parameters: {"signed_id"=>"eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBCdz09IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--77812323ea618480d0497c73b1b1cb96856a585a", "filename"=>"048496124_main_xxl"} ActiveStorage::Blob Load (0.2ms) SELECT "active_storage_blobs".* FROM "active_storage_blobs" WHERE "active_storage_blobs"."id" = ? LIMIT ? [["id", 2], ["LIMIT", 1]] Disk Storage (1.9ms) Generated URL for file at key: jpgplubo5jtvp1iefb02l82jlfdl (http://127.0.0.1:3000/rails/active_storage/disk/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaDdDVG9JYTJWNVNTSWhhbkJuY0d4MVltODFhblIyY0RGcFpXWmlNREpzT0RKcWJHWmtiQVk2QmtWVU9oQmthWE53YjNOcGRHbHZia2tpVzJGMGRHRmphRzFsYm5RN0lHWnBiR1Z1WVcxbFBTSXdORGcwT1RZeE1qUmZiV0ZwYmw5NGVHd3ViWEEwSWpzZ1ptbHNaVzVoYldVcVBWVlVSaTA0Snljd05EZzBPVFl4TWpSZmJXRnBibDk0ZUd3dWJYQTBCanNHVkRvUlkyOXVkR1Z1ZEY5MGVYQmxTU0lPZG1sa1pXOHZiWEEwQmpzR1ZEb1JjMlZ5ZG1salpWOXVZVzFsT2dwc2IyTmhiQT09IiwiZXhwIjoiMjAyMy0wNS0wNVQwMzoyOToyNC4xMzlaIiwicHVyIjoiYmxvYl9rZXkifX0=--c56634c4ae269745a756dbc26f32cf373f99b0c9/048496124_main_xxl.mp4) Redirected to http://127.0.0.1:3000/rails/active_storage/disk/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaDdDVG9JYTJWNVNTSWhhbkJuY0d4MVltODFhblIyY0RGcFpXWmlNREpzT0RKcWJHWmtiQVk2QmtWVU9oQmthWE53YjNOcGRHbHZia2tpVzJGMGRHRmphRzFsYm5RN0lHWnBiR1Z1WVcxbFBTSXdORGcwT1RZeE1qUmZiV0ZwYmw5NGVHd3ViWEEwSWpzZ1ptbHNaVzVoYldVcVBWVlVSaTA0Snljd05EZzBPVFl4TWpSZmJXRnBibDk0ZUd3dWJYQTBCanNHVkRvUlkyOXVkR1Z1ZEY5MGVYQmxTU0lPZG1sa1pXOHZiWEEwQmpzR1ZEb1JjMlZ5ZG1salpWOXVZVzFsT2dwc2IyTmhiQT09IiwiZXhwIjoiMjAyMy0wNS0wNVQwMzoyOToyNC4xMzlaIiwicHVyIjoiYmxvYl9rZXkifX0=--c56634c4ae269745a756dbc26f32cf373f99b0c9/048496124_main_xxl.mp4 Completed 302 Found in 8ms (ActiveRecord: 0.2ms | Allocations: 2139)
文件请求日志
Started GET "/rails/active_storage/disk/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaDdDVG9JYTJWNVNTSWhhbkJuY0d4MVltODFhblIyY0RGcFpXWmlNREpzT0RKcWJHWmtiQVk2QmtWVU9oQmthWE53YjNOcGRHbHZia2tpVzJGMGRHRmphRzFsYm5RN0lHWnBiR1Z1WVcxbFBTSXdORGcwT1RZeE1qUmZiV0ZwYmw5NGVHd3ViWEEwSWpzZ1ptbHNaVzVoYldVcVBWVlVSaTA0Snljd05EZzBPVFl4TWpSZmJXRnBibDk0ZUd3dWJYQTBCanNHVkRvUlkyOXVkR1Z1ZEY5MGVYQmxTU0lPZG1sa1pXOHZiWEEwQmpzR1ZEb1JjMlZ5ZG1salpWOXVZVzFsT2dwc2IyTmhiQT09IiwiZXhwIjoiMjAyMy0wNS0wNVQwMzoyOToyNC4xMzlaIiwicHVyIjoiYmxvYl9rZXkifX0=--c56634c4ae269745a756dbc26f32cf373f99b0c9/048496124_main_xxl.mp4" for 127.0.0.1 at 2023-05-04 23:24:24 -0400 Processing by ActiveStorage::DiskController#show as MP4 Parameters: {"encoded_key"=>"[FILTERED]", "filename"=>"048496124_main_xxl"} Completed 206 Partial Content in 3ms (ActiveRecord: 0.0ms | Allocations: 279)
预期行为
用户通过/signup页面注册,提交邮箱、密码、确认密码及视频文件;访问/video页面时,视频正常显示并自动播放。
已尝试/确认的操作
- 使用Video.js,现象一致
- 重启服务器
- 确认
user.video为ActiveStorage::Attached::One对象 - 尝试上传不同大小的视频(2GB和1MB)
- 浏览器开发者工具中确认视频源:
<video autoplay="true" type="video/mp4" src="http://127.0.0.1:3000/rails/active_storage/blobs/redirect/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBCdz09IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--77812323ea618480d0497c73b1b1cb96856a585a/048496124_main_xxl.mp4</video>
解决方案
1. 修复HTML标签解析问题
从开发者工具的输出可以看到,video标签的src属性未闭合,标签本身也未正确结束,这会导致浏览器解析异常:
<!-- 错误示例 --> <video autoplay="true" type="video/mp4" src="http://xxx...mp4</video>
修改视频页面的HTML代码,确保标签规范闭合,并添加浏览器自动播放兼容属性:
<video autoplay muted playsinline controls type="video/mp4" src="<%=@redirectURL%>"></video>
muted+playsinline:现代浏览器默认限制带声音的视频自动播放,这两个属性可绕过该限制controls:添加播放控件,方便手动测试排查问题
2. 优化ActiveStorage URL生成逻辑
当前使用url_for(@user.video)生成的是重定向URL(/rails/active_storage/blobs/redirect/...),虽然重定向本身合法,但直接使用服务URL可减少跳转环节,避免潜在解析问题。同时修正url_options的格式错误:
class VideoController < ApplicationController def index # url_options需要传入哈希格式,而非字符串 ActiveStorage::Current.url_options = { host: "http://127.0.0.1:3000" } if session[:user_id] @user = User.find(session[:user_id]) # 直接获取服务URL,同时判断视频是否已上传 @redirectURL = @user.video.service_url if @user.video.attached? end end end
3. 验证视频编码兼容性
部分MP4视频的编码格式可能不被浏览器支持,建议使用H.264视频编码+AAC音频编码的标准MP4文件。可通过FFmpeg重新编码:
ffmpeg -i input.mp4 -vcodec h264 -acodec aac output.mp4
4. 确认ActiveStorage配置正确性
检查config/storage.yml中的本地磁盘服务配置:
local: service: Disk root: <%= Rails.root.join("storage") %>
并在config/environments/development.rb中启用该服务:
config.active_storage.service = :local
测试步骤
- 应用上述修改后重启服务器
- 重新上传标准编码的MP4视频
- 访问
/video页面,观察视频播放状态,同时检查控制台是否有新错误提示
内容的提问来源于stack exchange,提问作者Jacob Chafin
相关产品推荐
相关产品推荐

