#!perl use strict; use CGI; use DateTime; use DateTime::Format::Mail; use Digest::MD5 qw(md5_hex); use Encode; use File::stat; use File::Basename; use File::Find::Rule; use MIME::Types; use URI::Escape; use Template; # File path where you store your media files in our $MediaPath = "G:"; # External web server (e.g. Apache, lighttpd) that mounts $MediaPath our $WebServer = "http://10.0.1.2/ext"; # Local Filesystem encoding. cp932 for Windows XP Japanese, utf-8 for Mac our $FileEncoding = "cp932"; # File Extension to serve in RSS feed our @Extensions = qw( avi divx mov flv wmv mp4 mpg mpeg mkv ); # Directory path to cache thumbnail images in our $ThumbPath = "Thumbs"; # Path to ffmpeg command. Used to generate thumbnails our $FFmpeg = "C:/FFMpeg/ffmpeg.exe"; my $query = CGI->new; my $re = "\.(" . join("|", @Extensions) . ')$'; my @files = File::Find::Rule->file->name( qr/$re/ )->in($MediaPath); my @media; for my $file (@files) { push @media, media_data(decode($FileEncoding, $file)); } @media = sort { $b->{mtime} <=> $a->{mtime} } @media; if ($ENV{GATEWAY_INTERFACE}) { # print CGI::header('application/rss+xml'); print $query->header('text/xml'); } binmode STDOUT, ":utf8"; my $format = DateTime::Format::Mail->new; my $stash = { media => \@media, path => $MediaPath, webserver => $WebServer, rfc822 => sub { $format->format_datetime($_[0]) }, }; my $tmpl = join '', ; my $tt = Template->new; $tt->process(\$tmpl, $stash) or die $tt->error; sub media_data { my $file = shift; my $base = File::Basename::basename($file, map ".$_", @Extensions); my $dir = File::Basename::dirname($file); $dir =~ s!^$MediaPath/!!; return if $dir =~ /^Recycle[dr]/i or $dir =~ /System Volume Information/; $base =~ s/_/ /g; $dir =~ s/_/ /g; if ($dir && $base !~ /\Q$dir\E/) { $base = "$dir - $base"; } my $tag_re = decode_utf8('[\[\(【]([^\)\]】]*)[\)\]】]'); my @tags; while ( $base =~ s/^$tag_re\s*|\s*$tag_re\.?$// ) { push @tags, $1 || $2; } my $thumb = md5_hex( encode_utf8($file) ) . ".jpg"; my $thumb_path = $MediaPath . "/" . $ThumbPath . "/" . $thumb; if (!-e $thumb_path) { create_thumb($file, $thumb_path); } my $stat = stat( encode($FileEncoding, $file) ); my $date = DateTime->from_epoch( epoch => $stat->mtime ); my $url = URI::Escape::uri_escape_utf8($file, "^A-Za-z0-9\-_.!~*'():/"); $url =~ s!^$MediaPath/!$WebServer/!; my $ext = ($file =~ /\.(\w+)$/)[0]; my $types = MIME::Types->new; $types->addType(MIME::Type->new( type => 'video/flv', extensions => [ 'flv' ] )); $types->addType(MIME::Type->new( type => 'video/x-matroska', extensions => [ 'mkv' ] )); $types->addType(MIME::Type->new( type => 'video/subtitle', extensions => [ 'sub', 'srt' ] )); $types->addType(MIME::Type->new( type => 'video/divx', extensions => [ 'divx' ] )); my $mime = $types->mimeTypeOf($ext); $mime = $mime ? $mime->type : 'application/octet-stream'; $base .= " (subtitle)" if $mime eq 'video/subtitle'; return { path => $file, title => $base, tags => \@tags, mtime => $date, url => $url, size => $stat->size, type => $mime, thumb => -s $thumb_path ? $WebServer . "/" . $ThumbPath . "/" . $thumb : undef, }; } sub create_thumb { my($input, $thumb) = @_; my $file = encode($FileEncoding, $input); system( $FFmpeg, "-i", $file, '-f' => 'image2', '-pix_fmt' => 'jpg', '-vframes' => 1, '-ss' => 3, '-s' => '704x396', # xxx to be configurable for 4:3 videos '-an', '-deinterlace', $thumb, ); if (!-s $thumb) { open my $out, ">", $thumb; # create empty file close $out; } } __DATA__ Index of [% path | html %] [% webserver | html %] [% FOREACH m = media %] [% m.title | html %] [% m.url | html %] [% rfc822(m.mtime) | html %] [% m.url | html %] [% m.title | html %] [% m.tags.join(', ') | html %] [% IF m.thumb %][% END %] [% END %]