<commit_before>class Video < SimpleDB::Base
  set_domain Panda::Config[:sdb_videos_domain]
  properties :filename, :original_filename, :parent, :status, :duration, :container, :width, :height, :video_codec, :video_bitrate, :fps, :audio_codec, :audio_bitrate, :audio_sample_rate, :profile, :profile_title, :player, :queued_at, :started_encoding_at, :encoding_time, :encoded_at, :last_notification_at, :notification, :updated_at, :created_at
  
  # TODO: state machine for status
  # An original video can either be 'empty' if it hasn't had the video file uploaded, or 'original' if it has
  # An encoding will have it's original attribute set to the key of the original parent, and a status of 'queued', 'processing', 'success', or 'error'
  
  def to_sym
    'videos'
  end
  
  # Classification
  # ==============
  
  def encoding?
    ['queued', 'processing', 'success', 'error'].include?(self.status)
  end
  
  # Finders
  # =======
  
  # Only parent videos (no encodings)
  def self.all
    self.query("['status' = 'original'] intersection ['created_at' != ''] sort 'created_at' desc", :load_attrs => true) # TODO: Don't throw an exception if attrs for a record in the search can't be found - it probably means its just been deleted
  end
  
  def self.recent_videos
    self.query("['status' = 'original']", :max_results => 10, :load_attrs => true)
  end
  
  def self.recent_encodings
    self.query("['status' = 'success']", :max_results => 10, :load_attrs => true)
  end
  
  def self.queued_encodings
    self.query("['status' = 'processing' or 'status' = 'queued']", :load_attrs => true)
  end
  
  def self.next_job
    # TODO: change to outstanding_jobs and remove .first
    self.query("['status' = 'queued']").first
  end
  
  def self.outstanding_notifications
    self.query("['notification' != 'success'] intersection ['status' = 'success' or 'status' = 'error']") #  sort 'last_notification_at' asc
  end
  
  # def self.recently_completed_videos
  #   self.query("['status' = 'success']")
  # end
  
  def parent_video
    self.class.find(self.parent)
  end
  
  def encodings
    self.class.query("['parent' = '#{self.key}']")
  end
  
  def find_encoding_for_profile(p)
    self.class.query("['parent' = '#{self.key}'] intersection ['profile' = '#{p.key}']")
  end
  
  # Attr helpers
  # ============
  
  def obliterate!
    self.delete_from_s3
    self.encodings.each do |e|
      e.delete_from_s3
      e.destroy!
    end
    self.destroy!
  end
  
  # Location to store video file fetched from S3 for encoding
  def tmp_filepath
    Panda::Config[:tmp_video_dir] / self.filename
  end
  
  # Has the actual video file been uploaded for encoding?
  def empty?
    self.status == 'empty'
  end
  
  def upload_redirect_url
    Panda::Config[:upload_redirect_url].gsub(/\$id/,self.key)
  end
  
  def state_update_url
    Panda::Config[:state_update_url].gsub(/\$id/,self.key)
  end
  
  def duration_str
    s = (self.duration.to_i || 0) / 1000
    "#{sprintf("%02d", s/60)}:#{sprintf("%02d", s%60)}"
  end
  
  def resolution
    self.width ? "#{self.width}x#{self.height}" : nil
  end
  
  def video_bitrate_in_bits
    self.video_bitrate.to_i * 1024
  end
  
  def audio_bitrate_in_bits
    self.audio_bitrate.to_i * 1024
  end
  
  def screenshot
    self.filename + ".jpg"
  end
  
  def thumbnail
    self.filename + "_thumb.jpg"
  end
  
  def screenshot_url
    %(http://#{Panda::Config[:videos_domain]}/#{self.screenshot})
  end
  
  def thumbnail_url
    %(http://#{Panda::Config[:videos_domain]}/#{self.thumbnail})
  end
  
  # Encding attr helpers
  # ====================
  
  def url
    %(http://#{Panda::Config[:videos_domain]}/#{self.filename})
  end
  
  def embed_html
    return nil unless self.encoding?
    %(<embed src="http://#{Panda::Config[:videos_domain]}/flvplayer.swf" width="#{self.width}" height="#{self.height}" allowfullscreen="true" allowscriptaccess="always" flashvars="&displayheight=#{self.height}&file=#{self.url}&width=#{self.width}&height=#{self.height}&image=#{self.screenshot_url}" />)
  end
  
  def embed_js
    return nil unless self.encoding?
  	%(
  	<div id="flash_container_#{self.key[0..4]}"><a href="http://www.macromedia.com/go/getflashplayer">Get the latest Flash Player</a> to watch this video.</div>
  	<script type="text/javascript">
      var flashvars = {};
      
      flashvars.file = "#{self.url}";
      flashvars.image = "#{self.screenshot_url}";
      flashvars.width = "#{self.width}";
      flashvars.height = "#{self.height}";
      flashvars.usefullscreen = "true";
      flashvars.skin = "http://#{Panda::Config[:videos_domain]}/kleur.swf";
      flashvars.controlbar = "over";
      var params = {wmode:"transparent"};
      var attributes = {};
      attributes.align = "top";
      swfobject.embedSWF("http://#{Panda::Config[:videos_domain]}/player.swf", "flash_container_#{self.key[0..4]}", "#{w}", "#{h}", "9.0.115", "http://#{Panda::Config[:videos_domain]}/expressInstall.swf", flashvars, params, attributes);
  	</script>
  	)
	end
  
  # S3
  # ==
  
  def upload_to_s3
    begin
      retryable(:tries => 5) do
        Merb.logger.info "Upload to S3"
        S3VideoObject.store(self.filename, File.open(self.tmp_filepath), :access => :public_read)
        sleep 3
      end
    rescue
      Merb.logger.error "Error uploading #{self.filename} to S3"
      raise
    else
      true
    end
  end
  
  def fetch_from_s3
    begin
      retryable(:tries => 5) do
        File.open(self.tmp_filepath, 'w') do |file|
          Merb.logger.info "Fetch from S3"
          S3VideoObject.stream(self.filename) {|chunk| file.write chunk}
        end
        sleep 3<commit_msg>using swfobject2<commit_after>class Video < SimpleDB::Base
  set_domain Panda::Config[:sdb_videos_domain]
  properties :filename, :original_filename, :parent, :status, :duration, :container, :width, :height, :video_codec, :video_bitrate, :fps, :audio_codec, :audio_bitrate, :audio_sample_rate, :profile, :profile_title, :player, :queued_at, :started_encoding_at, :encoding_time, :encoded_at, :last_notification_at, :notification, :updated_at, :created_at
  
  # TODO: state machine for status
  # An original video can either be 'empty' if it hasn't had the video file uploaded, or 'original' if it has
  # An encoding will have it's original attribute set to the key of the original parent, and a status of 'queued', 'processing', 'success', or 'error'
  
  def to_sym
    'videos'
  end
  
  # Classification
  # ==============
  
  def encoding?
    ['queued', 'processing', 'success', 'error'].include?(self.status)
  end
  
  # Finders
  # =======
  
  # Only parent videos (no encodings)
  def self.all
    self.query("['status' = 'original'] intersection ['created_at' != ''] sort 'created_at' desc", :load_attrs => true) # TODO: Don't throw an exception if attrs for a record in the search can't be found - it probably means its just been deleted
  end
  
  def self.recent_videos
    self.query("['status' = 'original']", :max_results => 10, :load_attrs => true)
  end
  
  def self.recent_encodings
    self.query("['status' = 'success']", :max_results => 10, :load_attrs => true)
  end
  
  def self.queued_encodings
    self.query("['status' = 'processing' or 'status' = 'queued']", :load_attrs => true)
  end
  
  def self.next_job
    # TODO: change to outstanding_jobs and remove .first
    self.query("['status' = 'queued']").first
  end
  
  def self.outstanding_notifications
    self.query("['notification' != 'success'] intersection ['status' = 'success' or 'status' = 'error']") #  sort 'last_notification_at' asc
  end
  
  # def self.recently_completed_videos
  #   self.query("['status' = 'success']")
  # end
  
  def parent_video
    self.class.find(self.parent)
  end
  
  def encodings
    self.class.query("['parent' = '#{self.key}']")
  end
  
  def find_encoding_for_profile(p)
    self.class.query("['parent' = '#{self.key}'] intersection ['profile' = '#{p.key}']")
  end
  
  # Attr helpers
  # ============
  
  def obliterate!
    self.delete_from_s3
    self.encodings.each do |e|
      e.delete_from_s3
      e.destroy!
    end
    self.destroy!
  end
  
  # Location to store video file fetched from S3 for encoding
  def tmp_filepath
    Panda::Config[:tmp_video_dir] / self.filename
  end
  
  # Has the actual video file been uploaded for encoding?
  def empty?
    self.status == 'empty'
  end
  
  def upload_redirect_url
    Panda::Config[:upload_redirect_url].gsub(/\$id/,self.key)
  end
  
  def state_update_url
    Panda::Config[:state_update_url].gsub(/\$id/,self.key)
  end
  
  def duration_str
    s = (self.duration.to_i || 0) / 1000
    "#{sprintf("%02d", s/60)}:#{sprintf("%02d", s%60)}"
  end
  
  def resolution
    self.width ? "#{self.width}x#{self.height}" : nil
  end
  
  def video_bitrate_in_bits
    self.video_bitrate.to_i * 1024
  end
  
  def audio_bitrate_in_bits
    self.audio_bitrate.to_i * 1024
  end
  
  def screenshot
    self.filename + ".jpg"
  end
  
  def thumbnail
    self.filename + "_thumb.jpg"
  end
  
  def screenshot_url
    %(http://#{Panda::Config[:videos_domain]}/#{self.screenshot})
  end
  
  def thumbnail_url
    %(http://#{Panda::Config[:videos_domain]}/#{self.thumbnail})
  end
  
  # Encding attr helpers
  # ====================
  
  def url
    %(http://#{Panda::Config[:videos_domain]}/#{self.filename})
  end
  
  def embed_html
    return nil unless self.encoding?
    %(<embed src="http://#{Panda::Config[:videos_domain]}/flvplayer.swf" width="#{self.width}" height="#{self.height}" allowfullscreen="true" allowscriptaccess="always" flashvars="&displayheight=#{self.height}&file=#{self.url}&width=#{self.width}&height=#{self.height}&image=#{self.screenshot_url}" />)
  end
  
  def embed_js
    return nil unless self.encoding?
  	%(
  	<div id="flash_container_#{self.key[0..4]}"><a href="http://www.macromedia.com/go/getflashplayer">Get the latest Flash Player</a> to watch this video.</div>
  	<script type="text/javascript">
      var flashvars = {};
      
      flashvars.file = "#{self.url}";
      flashvars.image = "#{self.screenshot_url}";
      flashvars.width = "#{self.width}";
      flashvars.height = "#{self.height}";
      flashvars.usefullscreen = "true";
      flashvars.skin = "http://#{Panda::Config[:videos_domain]}/kleur.swf";
      flashvars.controlbar = "over";
      var params = {wmode:"transparent"};
      var attributes = {};
      attributes.align = "top";
      swfobject.embedSWF("http://#{Panda::Config[:videos_domain]}/player.swf", "flash_container_#{self.key[0..4]}", "#{self.width}", "#{self.height}", "9.0.115", "http://#{Panda::Config[:videos_domain]}/expressInstall.swf", flashvars, params, attributes);
  	</script>
  	)
	end
  
  # S3
  # ==
  
  def upload_to_s3
    begin
      retryable(:tries => 5) do
        Merb.logger.info "Upload to S3"
        S3VideoObject.store(self.filename, File.open(self.tmp_filepath), :access => :public_read)
        sleep 3
      end
    rescue
      Merb.logger.error "Error uploading #{self.filename} to S3"
      raise
    else
      true
    end
  end
  
  def fetch_from_s3
    begin
      retryable(:tries => 5) do
        File.open(self.tmp_filepath, 'w') do |file|
          Merb.logger.info "Fetch from S3"
          S3VideoObject.stream(self.filename) {|chunk| file.write chunk}
        end
        sleep 3
{'fraction_non_alphanumeric': 0.15582131551178333, 'fraction_numerical': 0.008705592683784735, 'mean_word_length': 3.421850699844479, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 35, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '765050', 'n_tokens_mistral': 4027, 'n_tokens_neox': 3942, 'n_words': 856}