2016-04-08 17 views
-2

İki dizinli ortam sunucum var: Filmler ve TV Şovları. Bu dizinlerin her birinde, her giriş video dosyası ve altyazı dosyalarını içeren bir alt dizinde bulunur. Ben web dolaştılar ettik ve Michelle Sullivan mükemmel bir Perl buldukArdışık olarak medya dizinini HEVC'den h.264'e ffmpeg ile dönüştürün

, burada yayınlanan:

#!/usr/bin/perl 

use strict; 
use warnings; 

open DIR, "ls -1 |"; 
while (<DIR>) 
{ 
     chomp; 
     next if (-d "$_"); # skip directories 
     next unless (-r "$_"); # if it's not readable skip it! 
     my $file = $_; 
     open PROBE, "ffprobe -show_streams -of csv '$file' 2>/dev/null|" or die ("Unable to launch ffmpeg for $file! ($!)"); 
     my ($v, $a, $s, @c) = (0,0,0); 
     while (<PROBE>) 
     { 
       my @streaminfo = split(/,/, $_); 
       push(@c, $streaminfo[2]) if ($streaminfo[5] eq "video"); 
       $a++ if ($streaminfo[5] eq "audio"); 
       $s++ if ($streaminfo[5] eq "subtitle"); 
     } 
     close PROBE; 
     $v = scalar @c; 
     if (scalar @c eq 1 and $c[0] eq "ansi") 
     { 
       warn("Text file detected, skipping...\n"); 
       next; 
     } 
     warn("$file: Video Streams: $v, Audio Streams: $a, Subtitle Streams: $s, Video Codec(s): " . join (", ", @c) . "\n"); 
     if (scalar @c > 1) 
     { 
       warn("$file has more than one video stream, bailing!\n"); 
       next; 
     } 
     if ($c[0] eq "hevc") 
     { 
       warn("HEVC detected for $file ...converting to AVC...\n"); 
       system("mkdir -p h265"); 
       my @params = ("-hide_banner", "-threads 2"); 
       push(@params, "-map 0") if ($a > 1 or $s > 1 or $v > 1); 
       push(@params, "-c:a copy") if ($a); 
       push(@params, "-c:s copy") if ($s); 
       push(@params, "-c:v libx264 -pix_fmt yuv420p") if ($v); 
       if (system("mv '$file' 'h265/$file'")) 
       { 
         warn("Error moving $file -> h265/$file\n"); 
         next; 
       } 
       if (system("ffmpeg -xerror -i 'h265/$file' " . join(" ", @params) . " '$file' 2>/dev/null")) 
       { 
         warn("FFMPEG ERROR. Cannot convert $file restoring original...\n"); 
         system("mv 'h265/$file' '$file'"); 
         next; 
       } 
     } else { 
       warn("$file doesn't appear to need converting... Skipping...\n"); 
     } 
} 
close DIR; 

senaryo mükemmel gerçekleştirir - bu medyayı içeren dizinden içinde çalıştığı sürece.

Soruma Soru: Bu kod, kök dizinden yinelemeli olarak çalışacak şekilde değiştirilebilir mi? Nasıl?

Şimdiden teşekkürler.

(Michelle'in senaryo burada görülebilir: http://www.michellesullivan.org/blog/1636)

+0

http://perldoc.perl.org/File/Find.html Kodu, yukarıdaki döngüde, \ & wanted prameter olarak koydunuz. – skarface

+3

Ne istediğinden emin değilim ve gösterdiğiniz her şey başka birinin kodu. Bu Perl programını bulmak için * "web'i araştırdınız" diyorsunuz ve şimdi kendiniz için yaratma yeteneğinizi tahmin edemeyeceğiniz bir şey bulmak için tekrar gözden geçiriyorsunuz. Yığın Taşması, * belirli bir sorunla engellenen programcıların meslektaşlarından yardım isteyebileceği bir yerdir. Bir cehaletin onların gereksinimlerini buraya dökmesi ve bir çözüm beklemesi amaçlanmamıştır. – Borodin

cevap

1

Neden yinelemeli çalıştırmak istiyor musunuz? Belirli bir dizinin altındaki tüm dosyalar üzerinde çalıştırmak istediğiniz anlamına mı geliyor?

Bu problemde, işlemden işlenecek dosyaların listesini oluşturan parçayı ayırmayı tercih ediyorum. komut içine

while(<>) { 
    ... 
    } 

Boru listesinde:

$ find ... | script 

Veya bir dosyadan götürün: dosyaların uzun bir liste ile, standart yerine girişten satırları alabilir

$ script list_of_files.txt 

$ find ... -print0 | xargs -0 script 
: kısa bir liste ile

, ben favori xargs hile kullanıyor olabilir Bu durumda

Ben komut satırı argümanları geçer: Programda tüm bu yapmak istiyorsanız, siz File::Find kullanabilirsiniz

foreach (@ARGV) { 
    ... 
    } 

. Bunun ötesinde, birisinin sizin için işi yapmasını istemeniz gibi geliyor gibi görünüyor.

İlgili konular