AI Scanning

This commit is contained in:
Ryan
2026-09-13 14:38:14 -04:00
parent 458d8862cc
commit 01a5e50fcd
7 changed files with 212 additions and 72 deletions
+29
View File
@@ -0,0 +1,29 @@
FROM ubuntu:22.04
# Avoid interactive prompts during build
ENV DEBIAN_FRONTEND=noninteractive
ENV TZ=Etc/UTC
# System dependencies
# Install Perl, system deps, and ffmpeg (includes ffprobe)
RUN apt update && apt install -y \
libdbd-mysql-perl \
libhttp-lite-perl \
libjson-perl \
libyaml-perl \
perl \
libdbi-perl \
build-essential \
ffmpeg \
libstring-shellquote-perl \
libwww-perl \
liblwp-protocol-https-perl
RUN mkdir -p /app
ADD run.pl /app/run.pl
RUN chmod +x /app/run.pl
WORKDIR /app
# Default command: process tasks from the API until drained
CMD ["perl", "/app/run.pl"]
+32
View File
@@ -0,0 +1,32 @@
# VideoDetect — Worker service (standalone compose file)
# Run: docker compose -f aiworker/docker-compose.yml up -d
services:
worker:
build:
context: ./
dockerfile: Dockerfile
container_name: videodetect-aiworker
restart: "no"
environment:
- API_BASE_URL=${API_BASE_URL:-http://videodetect-api:3000}
- OLLAMA_URL=${OLLAMA_URL:-http://10.0.1.7:11434}
- SECONDS_PER_FRAME=${SECONDS_PER_FRAME:-30}
- TASK_COUNT=${TASK_COUNT:-50}
volumes:
- nas_input:/data:ro
- ./run.pl:/app/run.pl:ro
networks:
- videodetect_videodetect-network
volumes:
nas_input:
driver: local
driver_opts:
type: nfs
o: addr=10.0.0.2,ro,nfsvers=4,hard,intr
device: ":/mnt/Bulk/Homes/ryan/Prawns"
networks:
videodetect_videodetect-network:
external: true
+145
View File
@@ -0,0 +1,145 @@
#!/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'} || die "OLLAMA_URL environment variable not set\n";
my $api = $ENV{'API_BASE_URL'} || die "API_BASE_URL environment variable not set\n";
my $task_count = $ENV{'TASK_COUNT'} || 1;
my $sensitivity = 20;
my $resolution = "672:672";
chdir("/tmp") || die "Unable to change directory to /tmp: $!\n";
my $ua = LWP::UserAgent->new;
$ua->timeout(60);
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);
my $response = PostResponse($task_id, $ref->{'assign_key'}, $result);
}
print "Done\n";
exit(0);
sub CheckPath {
my ($path) = @_;
die "File path not set\n" unless $path;
die "File does not exist: $path\n" unless -e $path;
unlink(<*.png>);
system("ffmpeg -i \"$path\" -vf fps=1/$seconds,scale=$resolution output_%04d.png");
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' => 'srizon/pixie:latest',
'prompt' => "Are there any african american people or in this photo, whether they are shown completely or not? Please answer 'yes' or 'no' only.",
'images' => [$base64],
};
my $url = "$ollama/api/generate";
my $res = GetRest($url, $ref);
print "\t$res\n";
$total++;
if($res=~/yes/i) {
$yes++;
}
unlink($file);
}
my $percentage = ($yes*100)/$total;
print "$yes of $total images gave yes - $percentage\n";
my $verdict = 0;
if($percentage >= $sensitivity) {
print "Probably a black dude, $percentage\n";
$verdict = 1;
} else {
print "Probably not, $percentage\n";
$verdict = 0;
}
return {
'images' => $total,
'yes' => $yes,
'percentage'=> $percentage,
'verdict' => $verdict,
};
}
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;
}