178 lines
5.1 KiB
Perl
Executable File
178 lines
5.1 KiB
Perl
Executable File
#!/usr/bin/perl
|
|
use strict;
|
|
use MIME::Base64 qw(encode_base64);
|
|
use LWP::UserAgent;
|
|
use JSON;
|
|
use Data::Dumper;
|
|
|
|
my $seconds = $ENV{'SECONDS_PER_FRAME'} || 30;
|
|
my $ollama = $ENV{'OLLAMA_URL'} || 'http://10.0.1.7:11434';
|
|
my $api = $ENV{'API_BASE_URL'} || 'http://10.0.1.7:3000';
|
|
my $task_count = $ENV{'TASK_COUNT'} || 1;
|
|
my $image_count = $ENV{'IMAGE_COUNT'} || 10; # Number of images to extract from the video
|
|
my $min_time = $ENV{'MIN_TIME'} || 5; # Minimum time between images
|
|
my $sensitivity = 20;
|
|
my $resolution = "672:672";
|
|
#my $model = "hf.co/Jommarn/UNSEEN_Gemma_4_26B_NSFW-GGUF:Q8_0";
|
|
my $model = "hf.co/Jommarn/UNSEEN_Gemma_4_26B_NSFW-GGUF:Q5_K_M";
|
|
|
|
chdir("/tmp") || die "Unable to change directory to /tmp: $!\n";
|
|
|
|
my $ua = LWP::UserAgent->new;
|
|
$ua->timeout(60);
|
|
|
|
if(@ARGV) {
|
|
CheckPath($ARGV[0], {'duration' => 0});
|
|
|
|
exit;
|
|
}
|
|
|
|
for(my $i=0; $i<$task_count; $i++) {
|
|
my $ref = GetNext();
|
|
my $task = $ref->{'task'};
|
|
my $video = $ref->{'video'};
|
|
|
|
my $task_id = $task->{'id'};
|
|
my $video_id = $video->{'id'};
|
|
my $path = $video->{'file_path'};
|
|
my $result = CheckPath($path, $video);
|
|
|
|
next unless $result;
|
|
|
|
my $response = PostResponse($task_id, $ref->{'assign_key'}, $result);
|
|
}
|
|
|
|
print "Done\n";
|
|
exit(0);
|
|
|
|
sub CheckPath {
|
|
my ($path, $video) = @_;
|
|
die "File path not set\n" unless $path;
|
|
die "File does not exist: $path\n" unless -e $path;
|
|
|
|
unlink(<*.png>);
|
|
|
|
# Pick a frame interval that spreads $image_count frames across the video,
|
|
# but never more frequently than 1 frame per $min_time seconds.
|
|
my $interval = $seconds; # fallback if duration is unknown
|
|
if (my $duration = $video->{'duration'}) {
|
|
my $desired = $duration / $image_count;
|
|
$interval = ($desired > $min_time) ? $desired : $min_time;
|
|
}
|
|
|
|
system("ffmpeg -i \"$path\" -vf fps=1/$interval,scale=$resolution output_%04d.png 2>&1");
|
|
|
|
|
|
my $total=0;
|
|
my $yes=0;
|
|
$/ = undef;
|
|
foreach my $file (<*.png>) {
|
|
print "$file...\n";
|
|
open(IN, '<:raw', $file) || die "Unable to read $file: $!\n";
|
|
my $data = <IN>;
|
|
close(IN);
|
|
|
|
my $base64 = encode_base64($data);
|
|
$data=undef;
|
|
|
|
my $ref = {
|
|
'model' => $model,
|
|
'prompt' => "Are there any african american men in this photo, whether they are shown completely or not? Judge based on skin tone, accounting for shadows. Answer yes for very dark skin.Please answer 'yes' or 'no' only.",
|
|
'images' => [$base64],
|
|
};
|
|
|
|
my $url = "$ollama/api/generate";
|
|
my $res = GetRest($url, $ref);
|
|
print "$file\t$res\n";
|
|
#Remove thought information from the response
|
|
$res =~ s/<\|channel>.*?<channel\|>//s;
|
|
$res =~ s/^\s+|\s+$//g;
|
|
$total++;
|
|
if($res=~/yes/i) {
|
|
$yes++;
|
|
print "\tYES\n";
|
|
}
|
|
unlink($file);
|
|
}
|
|
|
|
if($total == 0) {
|
|
warn "No images were processed for $path\n";
|
|
return undef;
|
|
}
|
|
|
|
my $percentage = ($yes*100)/$total;
|
|
print "$yes of $total images gave yes - $percentage\n";
|
|
my $verdict = 0;
|
|
if($percentage >= $sensitivity) {
|
|
print "$path: Probably a black dude, $percentage\n";
|
|
$verdict = 1;
|
|
} else {
|
|
print "$path: Probably not, $percentage\n";
|
|
$verdict = 0;
|
|
}
|
|
return {
|
|
'images' => $total,
|
|
'yes' => $yes,
|
|
'percentage'=> $percentage,
|
|
'verdict' => $verdict,
|
|
'model' => $model,
|
|
'path' => $path,
|
|
|
|
};
|
|
}
|
|
|
|
sub GetRest {
|
|
my($url, $ref)=@_;
|
|
my $payload = encode_json($ref);
|
|
|
|
my $response = $ua->post($url, 'Content_Type' => 'application/json', 'Content' => $payload);
|
|
if($response->is_success) {
|
|
my $content = $response->decoded_content;
|
|
my @parts = split(/\n/, $content);
|
|
my @refs = map { decode_json($_) } @parts;
|
|
return join(' ', map { $_->{'response'} } @refs);
|
|
} else {
|
|
die "Error: " . $response->status_line;
|
|
}
|
|
}
|
|
|
|
sub PostResponse {
|
|
my ($task_id, $assign_key, $results) = @_;
|
|
my $url = "$api/api/v1/task/$task_id/complete";
|
|
my $ref = {
|
|
'assign_key' => $assign_key,
|
|
'results' => $results,
|
|
};
|
|
my $payload = encode_json($ref);
|
|
my $response = $ua->post($url, 'Content_Type' => 'application/json', 'Content' => $payload);
|
|
if($response->is_success) {
|
|
return $response->decoded_content;
|
|
} else {
|
|
die "Error posting response ($url): " . $response->status_line;
|
|
}
|
|
}
|
|
|
|
sub GetNext {
|
|
my $url = "$api/api/v1/nexttask/AISCAN";
|
|
my $task;
|
|
my $video;
|
|
|
|
my $response = $ua->get($url);
|
|
if($response->is_success) {
|
|
$task=decode_json($response->decoded_content);
|
|
} else {
|
|
die "Error fetching next task ($url): " . $response->status_line;
|
|
}
|
|
|
|
my $video_id = $task->{'task'}{'video_id'};
|
|
$url = "$api/api/v1/video/$video_id";
|
|
$response = $ua->get($url);
|
|
if($response->is_success) {
|
|
$video=decode_json($response->decoded_content);
|
|
$task->{'video'} = $video;
|
|
} else {
|
|
die "Error fetching video ($url): " . $response->status_line;
|
|
}
|
|
|
|
return $task;
|
|
} |