Ruby on rails 当您';你在使用后台工作人员吗?

Ruby on rails 当您';你在使用后台工作人员吗?,ruby-on-rails,ruby-on-rails-5,Ruby On Rails,Ruby On Rails 5,我正在制作一个应用程序,使用Streamio FFMPEG将视频从一种格式转换为另一种格式。我想向用户显示进度百分比,但我正在后台任务中进行代码转换(使用sidekiq和redis),因为代码转换可能需要相当长的时间才能完成 我不知道在浏览器中显示进度的理想方式是什么。对于Streamio,它提供了一种显示其进度的方法,如下所示: movie.transcode("movie.mp4") { |progress| puts progress } # 0.2 ... 0.5 ... 1.0 #

我正在制作一个应用程序,使用Streamio FFMPEG将视频从一种格式转换为另一种格式。我想向用户显示进度百分比,但我正在后台任务中进行代码转换(使用sidekiq和redis),因为代码转换可能需要相当长的时间才能完成

我不知道在浏览器中显示进度的理想方式是什么。对于Streamio,它提供了一种显示其进度的方法,如下所示:

movie.transcode("movie.mp4") { |progress| puts progress } # 0.2 ... 0.5 ... 1.0
# app/workers/convert_tomp4.rb

class ConvertTomp4
  include Sidekiq::Worker
  include Sidekiq::Status::Worker

  sidekiq_options retry: false

  def perform(original_file, attachment_id)
    destination_file="tmp/#{Digest::MD5.hexdigest(DateTime.now.to_s)}.mp4"
    puts "Transcoding #{original_file} into #{destination_file}"
    transcoding_options = %w(-f mp4 -vcodec libx264 -preset slow -acodec aac -b:v 2M -b:a 128k -strict -2)
    total 100
    at 0    
    movie=FFMPEG::Movie.new(original_file).transcode(destination_file,transcoding_options) { |p| at p*100 }
    attachment=Attachment.find(attachment_id)
    attachment.tomp4=File.open(destination_file)
    attachment.processing=false
    attachment.save
  end

end
如何将
progress
的值保存到以后可以在浏览器中检索到的内容中?我必须将其保存到变量中吗?归档?到数据库?正如我所说,我不知道这方面的最佳做法是什么。将其保存到数据库听起来会产生太多的开销,我不确定哪个变量可以在完成代码转换所需的时间内保存这些信息

为了简单起见,我们可以说,当访问某个页面时,这可以打印在一个简单的
标记中。稍后我将通过Javascript(使用Vue或React)执行更复杂的操作,以在进度发生变化时打印进度,但现在我只想知道如何检索进度

提前谢谢

更新

在jdno的帮助下,我成功地实现了这一点

首先,sidekiq安装状态。他们提到必须将它添加到sidekiq中间件中,在此之前,我不知道它“存在”。因此,要将其添加到创建此文件的中间件中,请执行以下操作:

# config/initializers/sidekiq.rb

require 'sidekiq'
require 'sidekiq-status'

Sidekiq.configure_client do |config|
  # accepts :expiration (optional)
  Sidekiq::Status.configure_client_middleware config, expiration: 30.minutes
end

Sidekiq.configure_server do |config|
  # accepts :expiration (optional)
  Sidekiq::Status.configure_server_middleware config, expiration: 30.minutes

  # accepts :expiration (optional)
  Sidekiq::Status.configure_client_middleware config, expiration: 30.minutes
end
然后,我用来对文件进行转码的worker如下所示:

movie.transcode("movie.mp4") { |progress| puts progress } # 0.2 ... 0.5 ... 1.0
# app/workers/convert_tomp4.rb

class ConvertTomp4
  include Sidekiq::Worker
  include Sidekiq::Status::Worker

  sidekiq_options retry: false

  def perform(original_file, attachment_id)
    destination_file="tmp/#{Digest::MD5.hexdigest(DateTime.now.to_s)}.mp4"
    puts "Transcoding #{original_file} into #{destination_file}"
    transcoding_options = %w(-f mp4 -vcodec libx264 -preset slow -acodec aac -b:v 2M -b:a 128k -strict -2)
    total 100
    at 0    
    movie=FFMPEG::Movie.new(original_file).transcode(destination_file,transcoding_options) { |p| at p*100 }
    attachment=Attachment.find(attachment_id)
    attachment.tomp4=File.open(destination_file)
    attachment.processing=false
    attachment.save
  end

end
Attachment
是我用来保存文件的模型,而
tomp4
是将文件信息保存到Carrierwave的字段<代码>处理是我用来知道辅助进程是否处于活动状态的字段,这只是多余的,但我想将其保存到主数据库中

请注意,我正在使用
{p|at p*100}
跟踪进度。通常,
p
的值在0.0到1.0之间,所以我用它乘以100来知道百分比。变量
at
是来自sidekiq状态的内置变量,就像
total
一样

最后,要获取视图中或应用程序中任何其他位置的值,我使用:

Sidekiq::Status::at @attachment.jobid
jobid
是在我将任务发送到队列之前分配的。以下是我在Carrierwave上载程序中使用的部分内容:

# app/uploaders/attachment_uploader.rb

def convert_to_mp4(arg1)
  if file.path
    if file.extension == 'mov'
      original = "#{root}/#{self.model.original.url}"
      job_id = ConvertTomp4.perform_async(original,self.model.id)
      Rails.logger.debug "Job ID: #{job_id}"
      self.model.jobid = job_id
      self.model.processing = true
      self.model.save
      Rails.logger.debug "Sending transcoding to the queue. #{original} with ID: #{job_id}"
    end
  end
end
请原谅这么多调试器行

original
是我用来保存原始文件的字段。到目前为止,我不知道如何保存上载文件的单一版本,因此我制作了第二个上载程序来处理转换后的文件,并将它们保存到我们用于此目的的
tomp4
。它将进度存储在Redis中,从而避免扩展数据库操作

您希望如何向客户公开信息取决于您的需要。对我们来说,进度更新非常缓慢,我们只需每隔几秒钟使用Javascript进行一次轮询。我们有一个表示任务的模型,例如
FileConversion
,具有
file\u path
size
等属性,然后通过
FileConversionController
公开作业的状态

对于我们的用例来说,这是一个非常好的解决方案,只需要您付出很少的努力。

我们使用它。它将进度存储在Redis中,从而避免扩展数据库操作

您希望如何向客户公开信息取决于您的需要。对我们来说,进度更新非常缓慢,我们只需每隔几秒钟使用Javascript进行一次轮询。我们有一个表示任务的模型,例如
FileConversion
,具有
file\u path
size
等属性,然后通过
FileConversionController
公开作业的状态


对于我们的用例来说,这是一个非常好的解决方案,只需要您付出很少的努力。

有趣的是,它看起来很有希望。我来看看。我正在检查gem的安装情况,在中间件链中添加一些东西让我有些不知所措。我能看到一个这样的例子吗?有趣的是,它看起来很有希望。我来看看。我正在检查gem的安装情况,在中间件链中添加一些东西让我有些不知所措。我能看到一个这样的例子吗?