解決したいこと
rails5.2でアプリを作成しています。video_tagで動画を埋め込み動画を再生させたいです。
動画の再生はJavascriptを用いて、動画の要素をタップ(クリック)すると再生される仕様です。
本番環境はAWS + Unicorn + Nginx + Capistranoでデプロイ済みです。
動画を再生させる画面はhome/index.html.erb
とposts/show.html.erb
の2ページです。
現状、PCではローカル環境と本番環境の両方で問題なく再生できます。しかし、本番環境のスマホデバイスでhome/index
の動画を再生しようとしても画面が真っ暗になったままでタップしても反応しません。(posts/show
では再生できます。)
なぜhome/index
の動画が再生されないのか原因が特定できなかったため、お力をお借りしたいです。。
動画のアップロードはCarrierWave
を使用しています。
開発環境
- macOS Catalina
- Ruby 2.6.5
- Ruby on Rails 5.2
イメージ画像(home/indexのページ)
本来なら動画の要素をタップすると再生されますが反応しません。
home/indexの該当コード
uploaders/post_video_uploader.rb
php:
1class PostVideoUploader < CarrierWave::Uploader::Base 2 # Include RMagick or MiniMagick support: 3 # include CarrierWave::RMagick 4 include CarrierWave::MiniMagick 5 6 # Choose what kind of storage to use for this uploader: 7 storage :file 8 # storage :fog 9 10 # Override the directory where uploaded files will be stored. 11 # This is a sensible default for uploaders that are meant to be mounted: 12 def store_dir 13 "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}" 14 end 15 16 # Provide a default URL as a default if there hasn't been a file uploaded: 17 # def default_url(*args) 18 # # For Rails 3.1+ asset pipeline compatibility: 19 # # ActionController::Base.helpers.asset_path("fallback/" + [version_name, "default.png"].compact.join('_')) 20 # 21 # "/images/fallback/" + [version_name, "default.png"].compact.join('_') 22 # end 23 24 # Process files as they are uploaded: 25 # process scale: [200, 300] 26 # 27 # def scale(width, height) 28 # # do something 29 # end 30 31 # Create different versions of your uploaded files: 32 # version :thumb do 33 # process resize_and_pad: [600, 700, "#000000", "Center"] 34 # end 35 36 # Add a white list of extensions which are allowed to be uploaded. 37 # For images you might use something like this: 38 def extension_whitelist 39 %w(MOV wmv mp4) 40 end 41 42 # Override the filename of the uploaded files: 43 # Avoid using model.id or version_name here, see uploader/store.rb for details. 44 # def filename 45 # "something.jpg" if original_filename 46 # end 47end
post.rb
php:
1class Post < ApplicationRecord 2 # Carrierwave 3 mount_uploader :post_video, PostVideoUploader 4 5 # バリデーション 6 validates :post_text, presence: true, length: { maximum: 140 } 7 validates :post_video, presence: true 8 9 # アソシエーション 10 belongs_to :user 11 12end
home_controller.rb
php:
1class HomeController < ApplicationController 2 3 def index 4 @posts = Post.all.includes(:user).order(id: "DESC") 5 end 6 7end
home/index.html.erb
php:home/index
1<% @posts.each do |post| %> 2 <li class="post-content"> 3 <%= video_tag(post.post_video.url, class: "postVideo") %> 4 <button id="playPause"></button> 5 : 6 : 7 </li> 8 : 9 : 10<% end %>
index.scss
php:index/scss
1.post-content { 2 3 .postVideo { 4 display: block; // videoタグはインライン要素なのでdisplay:blockを設定 5 width: 100vw; 6 max-height: 300px; 7 min-height: 220px; 8 object-fit: contain; 9 } 10 #playPause { 11 display: block; 12 background: none; 13 border: 0; 14 outline: 0; 15 width: 100%; // 動画のどの部分をタップしても再生されるように幅と高さを100%に 16 height: 100%; 17 color: #FFF; 18 } 19}
index.js
php:index.js
1$(window).on('load', function() { 2 (() => { 3 4 const $btn = document.querySelectorAll('#playPause'); 5 6 const handleClick = (e) => { 7 const $this = e.target; 8 const $target_video = $this.previousElementSibling; 9 10 //動画の再生/停止の関数 11 function togglePlayPause() { 12 if($target_video.paused) { 13 $this.className = "pause"; 14 $target_video.play(); 15 } 16 else { 17 $this.className = "play"; 18 $target_video.pause(); 19 } 20 } 21 // buttonがタップされたら、togglePlayPause()関数を呼び出す 22 $this.onclick = function() { 23 togglePlayPause(); 24 }; 25 }); 26 } 27 28 // 全$btnに関数を適用 29 let index = 0; 30 while(index < $btn.length) { 31 $btn[index].addEventListener('click', (e) => handleClick(e)); 32 index++; 33 } 34 35 })(); 36});
posts/showの該当コード
posts_controller.rb
php:
1class PostsController < ApplicationController 2 : 3 : 4 def show 5 @post = Post.find_by(id: params[:id] ) 6 end 7 : 8 : 9end
posts/show.html.erb
php:
1<li class="post-content"> 2 <%= video_tag(@post.post_video.url, class: "showPostVideo") %> 3 <button id="showPlayPause"></button> 4 : 5 : 6</li>
show-post.js
php:
1$(window).on('load', function() { 2 (() => { 3 const $video = document.querySelector('.showPostVideo'); 4 const $btn = document.getElementById('showPlayPause'); 5 6 function togglePlayPause() { 7 if($video.paused) { 8 $btn.className = 'pause'; 9 $video.play(); 10 } else { 11 $btn.className = 'play'; 12 $video.pause(); 13 } 14 } 15 16 $btn.onclick = function() { 17 togglePlayPause(); 18 } 19 20 })(); 21})
cssはhome/index
と同じです。posts/show.html.erb
の画面ではスマホデバイスでも問題なく再生されます。
仮説と試したこと
- javascriptが読み込まれてない?→他のJSファイルは問題なく読み込まれてる
- videoのリクエストが送られてない?→ステータスコードが206なのでリクエストは送られている
- videoタグに
controls:true
を設定してデフォルトのコントロールパネルだと再生できる - videoタグに
autoplay:true
,muted:true
,playsinline:true
を設定すると問題なく自動再生される
PCでは本番環境で問題なく再生できるので、スマホデバイス特有の仕様が絡んでいるのではないかと考えていますが、原因が特定できないです。もしくはJavascriptの文法に問題があるのでしょうか。。
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。