2023-02-02 06:42:50 +00:00
|
|
|
require 'uri'
|
2023-04-10 03:27:20 +00:00
|
|
|
require 'fileutils'
|
2023-02-02 06:42:50 +00:00
|
|
|
class VideoImage
|
|
|
|
include Mongoid::Document
|
|
|
|
include Mongoid::Timestamps
|
|
|
|
include OrbitModel::Status
|
|
|
|
include OrbitModel::Impression
|
|
|
|
include OrbitTag::Taggable
|
|
|
|
include OrbitCategory::Categorizable
|
|
|
|
include Slug
|
|
|
|
mount_uploader :file, VideoDataImageUploader
|
|
|
|
mount_uploader :video_snapshot, VideoDataImageUploader
|
|
|
|
mount_uploader :video_file, VideoDataUploader
|
|
|
|
mount_uploader :video_file_webm, VideoDataUploader
|
|
|
|
field :default_video_snapshot, type: Boolean, default: false
|
|
|
|
field :auto_convert_video, type: Boolean, default: false
|
|
|
|
field :title, as: :slug_title, type: String, localize: true
|
|
|
|
field :keyword, type: String, localize: true
|
|
|
|
field :desc, type: String, localize: true
|
|
|
|
# field :weight, type: Integer, default: 1
|
|
|
|
# field :out_link, type: String
|
|
|
|
# field :link_open, type: String
|
|
|
|
field :postdate , type: Date, default: Date.today
|
|
|
|
field :deadline , type: Date
|
|
|
|
field :is_youtube, type: Boolean, default: false
|
|
|
|
field :youtube , type: String
|
|
|
|
field :youtube_id, type: String
|
|
|
|
field :sort_number, type: Integer
|
|
|
|
field :language_enabled, type: Array, default: ["en","zh_tw"]
|
|
|
|
field :exchange_item, default: "1" # 1=>youtube, 2=>video file, 3=>image
|
|
|
|
field :use_override_post_agency, type: Boolean, default: false
|
|
|
|
field :override_post_agency, type: Integer, default: 0
|
|
|
|
field :create_user_id
|
|
|
|
field :update_user_id
|
|
|
|
field :view_count, type: Integer, default: 0
|
|
|
|
field :scale, type: Float
|
|
|
|
# LINK_OPEN_TYPES = ["local", "new_window"]
|
|
|
|
|
|
|
|
# before_save :add_http
|
|
|
|
# validates :file, presence: true
|
|
|
|
# validates :out_link, format: {:with=> /\A(http:\/\/|https:\/\/|\/)/i}, allow_blank: true
|
|
|
|
# validates :title, presence: true
|
|
|
|
scope :open_in_future, ->{where(:is_hidden.ne=>true,:is_preview.ne => true,:postdate.gt=>Time.now).order(postdate: :asc)}
|
|
|
|
scope :can_display, ->{where(:is_hidden.ne=>true).valid_time_range}
|
|
|
|
scope :can_display_and_sorted, ->{can_display.sorted}
|
|
|
|
scope :valid_time_range, ->{any_of({:postdate.lte=>Time.now, :deadline.gte=>Time.now},{:postdate.lte=>Time.now, :deadline=>nil},{:postdate=>nil,:deadline.gte=>Time.now},{:postdate=>nil,:deadline=>nil})}
|
|
|
|
scope :sorted, ->{order({is_top: :desc,postdate: :desc,id: :desc})}
|
|
|
|
|
|
|
|
scope :is_expired, ->{self.and(VideoImage.unscoped.or({:deadline.lte=>Time.now}).selector)}
|
|
|
|
scope :not_expired, ->{self.and(VideoImage.unscoped.or({:deadline.gte=>Time.now},{:deadline=>nil}).selector)}
|
|
|
|
before_save do
|
|
|
|
unless @skip_callback
|
|
|
|
uri = URI.parse(self.youtube) rescue nil
|
|
|
|
self.is_youtube = (uri && uri.host == "www.youtube.com")
|
|
|
|
if self.is_youtube
|
|
|
|
if uri.path.start_with?('/embed/')
|
|
|
|
self.youtube_id = uri.path.split('/embed/').last.split(/[\/#?]/).first
|
|
|
|
if self.youtube_id.blank?
|
|
|
|
self.is_youtube = false
|
|
|
|
self.youtube_id = nil
|
|
|
|
end
|
|
|
|
else
|
|
|
|
params = CGI.parse(uri.query.to_s)
|
|
|
|
v = params.blank? ? nil : params['v'].first
|
|
|
|
if v.blank?
|
|
|
|
self.is_youtube = false
|
|
|
|
self.youtube_id = nil
|
|
|
|
else
|
|
|
|
self.youtube_id = v
|
|
|
|
end
|
|
|
|
end
|
|
|
|
if self.is_youtube
|
|
|
|
begin
|
2023-04-10 09:22:44 +00:00
|
|
|
youtube_img_url = "https:"+self.youtube_thumb
|
|
|
|
uri = URI.parse(youtube_img_url)
|
|
|
|
req = Net::HTTP::Get.new(uri.path)
|
|
|
|
res = Net::HTTP.start( uri.host, uri.port,
|
|
|
|
:use_ssl => (uri.scheme == 'https'),
|
|
|
|
:verify_mode => OpenSSL::SSL::VERIFY_NONE) do |https|
|
|
|
|
https.request(req)
|
|
|
|
end
|
|
|
|
snapshot_content = res.body rescue nil #Net::HTTP.get_response(URI.parse(youtube_img_url)).body rescue nil
|
2023-04-10 03:27:20 +00:00
|
|
|
if snapshot_content
|
|
|
|
self[:video_snapshot] = '0.jpg'
|
|
|
|
snapshot_file_path = self.video_snapshot.file.path
|
|
|
|
FileUtils.mkdir_p(File.dirname(snapshot_file_path))
|
|
|
|
File.open(snapshot_file_path, 'wb'){|f| f.write(snapshot_content)}
|
|
|
|
image = MiniMagick::Image.open(snapshot_file_path)
|
|
|
|
self.scale = (1.0 * image[:height] / image[:width] * 100).round(2)
|
|
|
|
else
|
|
|
|
puts "cannot read #{youtube_img_url}"
|
|
|
|
end
|
2023-02-02 06:42:50 +00:00
|
|
|
rescue => e
|
|
|
|
puts e.to_s
|
|
|
|
self.scale = nil
|
|
|
|
end
|
|
|
|
else
|
|
|
|
self.scale = nil
|
|
|
|
end
|
|
|
|
else
|
|
|
|
self.youtube_id = nil
|
|
|
|
image = MiniMagick::Image.open(self.video_snapshot.file.path) rescue nil
|
|
|
|
if image
|
|
|
|
self.scale = (1.0 * image[:height] / image[:width] * 100).round(2)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
if self.video_snapshot_changed?
|
|
|
|
self.default_video_snapshot = false
|
|
|
|
end
|
|
|
|
VideoProSetting.first.update_user_id(self)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
after_destroy do
|
|
|
|
VideoProSetting.first.remove_user_id(self)
|
|
|
|
end
|
|
|
|
after_save do
|
|
|
|
unless @skip_callback
|
|
|
|
if (self.video_file_changed? || self.auto_convert_video_changed?) && self.auto_convert_video
|
|
|
|
Thread.new do
|
|
|
|
self.generate_webm
|
|
|
|
end
|
|
|
|
end
|
|
|
|
if self.video_file? && self.video_file_changed? && (!(self.video_snapshot?) || self.default_video_snapshot)
|
|
|
|
Thread.new do
|
|
|
|
self.generate_video_snapshot
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
def inc_count
|
|
|
|
self.class.where(:id=>self.id).update_all({"$inc"=>{"view_count"=>1}})
|
|
|
|
end
|
|
|
|
def category_title
|
|
|
|
self.category.title rescue ""
|
|
|
|
end
|
|
|
|
def post_agencies_translations
|
|
|
|
if defined?(OrbitHelper::SharedHash) && OrbitHelper::SharedHash
|
|
|
|
OrbitHelper::SharedHash['video_pro'][:post_agencies_translations] rescue VideoProSetting.first.post_agencies_translations
|
|
|
|
else
|
|
|
|
VideoProSetting.first.post_agencies_translations rescue {}
|
|
|
|
end
|
|
|
|
end
|
|
|
|
def get_override_post_agency
|
|
|
|
self.post_agencies_translations[I18n.locale.to_s][self.override_post_agency] rescue ""
|
|
|
|
end
|
|
|
|
def post_agency(video_pro_setting=nil)
|
|
|
|
if self.use_override_post_agency
|
|
|
|
self.get_override_post_agency
|
|
|
|
else
|
|
|
|
if video_pro_setting.nil?
|
|
|
|
video_pro_setting = VideoProSetting.first
|
|
|
|
end
|
|
|
|
if video_pro_setting && video_pro_setting.enable_name_mapping
|
|
|
|
tmp = video_pro_setting.user_mapping[self.update_user_id] rescue nil
|
|
|
|
if tmp.blank?
|
|
|
|
user_name = User.where(:id=>self.update_user_id).pluck(:member_name).first[I18n.locale.to_s] rescue nil
|
|
|
|
else
|
|
|
|
user_name = tmp
|
|
|
|
end
|
|
|
|
else
|
|
|
|
user_name = User.where(:id=>self.update_user_id).pluck(:member_name).first[I18n.locale.to_s] rescue nil
|
|
|
|
end
|
|
|
|
user_name
|
|
|
|
end
|
|
|
|
end
|
|
|
|
def generate_video_snapshot
|
|
|
|
if self.video_file?
|
|
|
|
self.default_video_snapshot = true
|
|
|
|
self[:video_snapshot] = File.basename(self.video_file.file.path).split(/\.[^.]+$/)[0] + ".jpg"
|
|
|
|
FileUtils.mkdir_p(File.dirname(self.video_snapshot.file.path))
|
|
|
|
system("tmp/ffmpeg/ffmpeg -i #{self.video_file.file.path} -vframes 1 #{self.video_snapshot.file.path}")
|
|
|
|
@skip_callback = true
|
|
|
|
self.save
|
|
|
|
@skip_callback = false
|
|
|
|
true
|
|
|
|
end
|
|
|
|
end
|
|
|
|
def generate_webm
|
|
|
|
video_path = self.video_file.path rescue nil
|
|
|
|
if !video_path.blank?
|
|
|
|
video_webm = video_path.split('.')[0...-1].join('.')+".webm"
|
|
|
|
core_num = [`cat /proc/cpuinfo | grep processor | wc -l`.to_i/2,1].max
|
|
|
|
flag = system("tmp/ffmpeg/ffmpeg -i #{video_path} -c:v libvpx-vp9 -crf 35 -b:v 0 -b:a 96k -c:a libopus -filter:v fps=20 #{video_webm} -cpu-used #{core_num}")
|
|
|
|
if flag
|
|
|
|
self.video_file_webm = File.open(video_webm)
|
|
|
|
@skip_callback = true
|
|
|
|
self.save
|
|
|
|
@skip_callback = false
|
|
|
|
true
|
|
|
|
else
|
|
|
|
puts "generate webm failed"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def expired?
|
|
|
|
self.deadline<Time.now rescue false
|
|
|
|
end
|
|
|
|
|
|
|
|
def embed_url
|
|
|
|
if self.is_youtube
|
|
|
|
return "//www.youtube.com/embed/#{self.youtube_id}"
|
|
|
|
else
|
|
|
|
return ""
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def youtube_thumb
|
|
|
|
if self.is_youtube
|
|
|
|
return "//img.youtube.com/vi/#{self.youtube_id}/0.jpg"
|
|
|
|
else
|
|
|
|
return ""
|
|
|
|
end
|
|
|
|
end
|
|
|
|
def statuses
|
|
|
|
statuses = []
|
|
|
|
statuses << top_text if is_top?
|
|
|
|
statuses << hot_text if is_hot?
|
|
|
|
statuses << hidden_text if is_hidden?
|
|
|
|
statuses
|
|
|
|
end
|
|
|
|
def statuses_with_classname
|
|
|
|
statuses = []
|
|
|
|
statuses << {"name" => top_text, "classname" => "top"} if is_top?
|
|
|
|
statuses << {"name" => hot_text, "classname" => "hot"} if is_hot?
|
|
|
|
statuses << {"name" => hidden_text, "classname" => "hidden"} if is_hidden?
|
|
|
|
statuses
|
|
|
|
end
|
|
|
|
def status_for_table
|
|
|
|
status = ""
|
|
|
|
status << "<span class='label label-success'>#{top_text}</span> " if self.is_top
|
|
|
|
status << "<span class='label label-important'>#{hot_text}</span> " if self.is_hot
|
|
|
|
status << "<span class='label'>#{hidden_text}</span>"if self.is_hidden
|
|
|
|
status.html_safe
|
|
|
|
end
|
|
|
|
def top_text
|
|
|
|
I18n.t("announcement.status.top")
|
|
|
|
end
|
|
|
|
def hot_text
|
|
|
|
I18n.t("announcement.status.hot")
|
|
|
|
end
|
|
|
|
def hidden_text
|
|
|
|
I18n.t("announcement.status.hidden")
|
|
|
|
end
|
|
|
|
|
|
|
|
def get_snapshot_url
|
2023-04-10 03:27:20 +00:00
|
|
|
self.video_snapshot.url rescue ""
|
|
|
|
# (self.is_youtube ? self.youtube_thumb : (self.video_snapshot.url))
|
2023-02-02 06:42:50 +00:00
|
|
|
end
|
|
|
|
protected
|
|
|
|
|
|
|
|
def add_http
|
|
|
|
# unless self.out_link.blank? || self.out_link[/^http:\/\//] || self.out_link[/^https:\/\//] || self.out_link[/^\//]
|
|
|
|
# self.out_link = 'https://' + self.out_link
|
|
|
|
# end
|
|
|
|
end
|
|
|
|
end
|