/** * Execute the job. * * @return void */ public function handle(MatcherContract $matcher) { // Mark this media as processing $this->media->status = Media::STATUS_PROCESSING; $this->media->save(); $duplitron_media = $matcher->getMedia($this->media->duplitron_id); // Update the media to reflect the duplitron's values // TODO: this should be done when the media is created, not in this process $this->media->archive_id = $duplitron_media->external_id; $this->media->media_path = $duplitron_media->media_path; $this->media->save(); // Step 1: Register this as a distractor $register_task = $matcher->startTask($duplitron_media, MatcherContract::TASK_ADD_DISTRACTOR); $register_task = $matcher->resolveTask($register_task); // Step 2: Deregister this as a potential target $deregister_task = $matcher->startTask($duplitron_media, MatcherContract::TASK_REMOVE_POTENTIAL_TARGET); $deregister_task = $matcher->resolveTask($deregister_task); // Step 3: Run a match $match_task = $matcher->startTask($duplitron_media, MatcherContract::TASK_MATCH); $match_task = $matcher->resolveTask($match_task); // Step 4: Remove any matched media in the potential targets list $potential_targets = $match_task->result->data->matches->potential_targets; foreach ($potential_targets as $potential_target) { // Deregister the potential target $matched_media = $potential_target->destination_media; // First make sure the match is significant $match_duration = $potential_target->duration; $matched_media_duration = $matched_media->duration; if ($match_duration / $matched_media_duration < 0.6) { continue; } $deregister_task = $matcher->startTask($matched_media, MatcherContract::TASK_REMOVE_POTENTIAL_TARGET); $deregister_task = $matcher->resolveTask($deregister_task); } // Mark this media as processed $this->media->status = Media::STATUS_STABLE; $this->media->save(); }
/** * Execute the job. * * @return void */ public function handle(MatcherContract $matcher) { // Mark this media as processing $this->media->status = Media::STATUS_PROCESSING; $this->media->save(); /////////// // Add the media to the API $duplitron_media = $matcher->addMedia($this->media); $this->media->duplitron_id = $duplitron_media->id; $this->media->save(); // If it's not in the corpus, add it if (!$duplitron_media->match_categorization->is_corpus) { $corpus_task = $matcher->startTask($duplitron_media, MatcherContract::TASK_ADD_CORPUS); $matcher->resolveTask($corpus_task); if ($corpus_task->status->code == MatcherContract::STATUS_FAILED) { $this->media->status = Media::STATUS_FAILED; $this->media->save(); return; } } Log::info("Starting to process: " . $this->media->duplitron_id); // Add media to the corpus // This needs to be done before matching to ensure no comparisons are missed in multithreaded environments // Match against targets // Programs after election day should not be compared to past programs $id_parts = explode($this->media->archive_id); if ((int) $id_parts[1] <= 20161108) { $match_task = $matcher->startTask($duplitron_media, MatcherContract::TASK_MATCH_TARGETS); $match_task = $matcher->resolveTask($match_task); // Run the match command // $match_task = $matcher->startTask($duplitron_media, MatcherContract::TASK_MATCH); // $match_task = $matcher->resolveTask($match_task); // If the task failed, move along if ($match_task->status->code == MatcherContract::STATUS_FAILED) { $this->media->status = Media::STATUS_FAILED; $this->media->save(); return; } // Get the list of target matches $matches = $match_task->result->data->matches; $targets = $matches->targets; // Register the targets foreach ($targets as $target) { // Skip matches that are too short if ($target->duration < env('DUPLITRON_MIN_DURATION')) { continue; } // Skip matches that are too long if ($target->duration > env('DUPLITRON_MAX_DURATION')) { continue; } // Skip matches with a confidence level that is too low $confidence = $target->consecutive_hashes / $target->common_hashes; if ($confidence < env('DUPLITRON_MIN_HASH_RATIO')) { continue; } $start = $target->start; $end = $target->start + $target->duration; $instance_id = $this->media->archive_id; $canonical_id = $target->destination_media->external_id; $matcher->registerCanonicalInstance($canonical_id, $instance_id, $start, $end); } } // Mark this media as processed $this->media->status = Media::STATUS_STABLE; $this->media->save(); }
/** * Execute the job. * * @return void */ public function handle(MatcherContract $matcher) { // Mark this media as processing $this->media->status = Media::STATUS_PROCESSING; $this->media->save(); // Add this media to the duplitron if it hasn't been added already if (!$this->media->duplitron_id) { $duplitron_media = $matcher->addMedia($this->media); $this->media->duplitron_id = $duplitron_media->id; $this->media->save(); } Log::info("Starting to process: " . $this->media->duplitron_id); // Load the latest duplitron media $duplitron_media = $matcher->getMedia($this->media->duplitron_id); // Update the media to reflect the duplitron's values // TODO: this should be done when the media is created, not in this process $this->media->archive_id = $duplitron_media->external_id; $this->media->media_path = $duplitron_media->media_path; $this->media->save(); // Step 1: Register this as a target // ... unless it is already a target if (!$duplitron_media->match_categorization->is_target) { $register_task = $matcher->startTask($duplitron_media, MatcherContract::TASK_ADD_TARGET); $register_task = $matcher->resolveTask($register_task); } // Step 2: Deregister this as a potential target // $deregister_task = $matcher->startTask($duplitron_media, MatcherContract::TASK_REMOVE_POTENTIAL_TARGET); // $deregister_task = $matcher->resolveTask($deregister_task); // Step 3: Deregister this as a distractor // $deregister_task = $matcher->startTask($duplitron_media, MatcherContract::TASK_REMOVE_DISTRACTOR); // $deregister_task = $matcher->resolveTask($deregister_task); // Step 4: Run a match $parameters = array("end_date" => "2016-11-08", "start_date" => "2016-10-01"); $match_task = $matcher->startTask($duplitron_media, MatcherContract::TASK_FULL_MATCH, $parameters); $match_task = $matcher->resolveTask($match_task); // Before moving forward, make sure we got data back if ($match_task) { // Step 5: Look for all instances of this among the corpus $instances = $match_task->result->data->matches->corpus; // Sort them in order of start time // NOTE: right now there is a known bug where audfprint will sometimes have TWO copies of an ad, split up! // By inserting in order we will passively drop the duplicate due to overlap on backend // Eventually we should make the matches more accurate *and* handle overlap on frontend. $target_start_sort = function ($a, $b) { if ($a->target_start < $b->target_start) { return -1; } if ($a->target_start > $b->target_start) { return 1; } return 0; }; foreach ($instances as $instance) { // Skip matches that are too short if ($instance->duration < env('DUPLITRON_MIN_DURATION')) { continue; } // Skip matches that are too long if ($instance->duration > env('DUPLITRON_MAX_DURATION')) { continue; } // Skip matches with a confidence level that is too low $confidence = $instance->consecutive_hashes / $instance->common_hashes; if ($confidence < env('DUPLITRON_MIN_HASH_RATIO')) { continue; } $start = $instance->target_start; $end = $start + $instance->duration; $canonical_id = $this->media->archive_id; $instance_id = $instance->destination_media->external_id; $matcher->registerCanonicalInstance($canonical_id, $instance_id, $start, $end); } } // Mark this media as processed $this->media->status = Media::STATUS_STABLE; $this->media->save(); }