Скенер на фолдери

Прочитај ги патеките и должините на видео фајловите директно од компјутерот.

ЧЕКОР 1

Преземи и стартувај

Зачувај ја скриптата во фолдер по избор. Десен клик → Run with PowerShell, или во PowerShell: .\Skener-Biblioteka.ps1

ЧЕКОР 2

Наведи фолдери

Стандардно скенира \\192.168.88.88\Lokalen и \\NASVISTV\Lokalen. За свои: .\Skener-Biblioteka.ps1 -Folders "\\NAS\Lokalen\MUZIKA"

ЧЕКОР 3

Качи biblioteka.csv

Добиениот CSV качи го на страницата Библиотека. Секое ново скенирање само ги дополнува новите фајлови.

Формат на CSV

Точка-запирка како разделник, UTF-8. Апликацијата чита и вредности како00:32:35 за должина и хексадецимална големина.

path;duration_ms;size_bytes;width;height;fps_num;fps_den;audio_rate;audio_channels;audio_lang

Со ffprobe.exe до скриптата се читаат точни fps и аудио податоци; без него се користат метаподатоците на Windows.

Skener-Biblioteka.ps1

# ===============================================================
#  Vistel Playout - Media Library Scanner
#  Creates a CSV with path, duration, size, resolution, fps and audio.
#  Usage (PowerShell):
#     .\Skener-Biblioteka.ps1
#  Or with custom folders:
#     .\Skener-Biblioteka.ps1 -Folders "\\192.168.88.88\Lokalen\EMISII","\\NASVISTV\Lokalen\MUZIKA"
#  For exact fps/audio metadata, put ffprobe.exe next to this script (optional).
# ===============================================================

param(
  [string[]]$Folders = @(
    "\\192.168.88.88\Lokalen",
    "\\NASVISTV\Lokalen"
  ),
  [string]$Output = "",
  [string[]]$Extensions = @(".mp4",".mov",".mxf",".mkv",".avi",".mpg",".mpeg",".ts",".wmv",".m4v"),
  [string[]]$ExcludeFolders = @(
    "\\NASVISTV\Lokalen\ARHIVA KADRI"
  )
)

$ErrorActionPreference = "Continue"

# Use the script directory, or Desktop when no script directory is available.
$baseDir = $PSScriptRoot
if ([string]::IsNullOrWhiteSpace($baseDir)) { $baseDir = [Environment]::GetFolderPath("Desktop") }
if ([string]::IsNullOrWhiteSpace($baseDir)) { $baseDir = $env:USERPROFILE }
if ([string]::IsNullOrWhiteSpace($Output)) { $Output = Join-Path $baseDir "biblioteka.csv" }

$ffprobe = Join-Path $baseDir "ffprobe.exe"
$useFfprobe = Test-Path $ffprobe


$shell = New-Object -ComObject Shell.Application
$rows = New-Object System.Collections.Generic.List[string]
$rows.Add("path;duration_ms;size_bytes;width;height;fps_num;fps_den;audio_rate;audio_channels;audio_lang")

function Get-ShellMeta($file) {
  try {
    $folder = $shell.Namespace($file.DirectoryName)
    if ($null -eq $folder) { return $null }
    $item = $folder.ParseName($file.Name)
    if ($null -eq $item) { return $null }
    $dur = $folder.GetDetailsOf($item, 27)   # Duration hh:mm:ss
    $dim = $folder.GetDetailsOf($item, 31)   # Dimensions
    $rate = $folder.GetDetailsOf($item, 315) # Frame rate (1000 * fps)
    $ms = 0
    if ($dur -match "(\d+):(\d+):(\d+)") {
      $ms = ([int]$Matches[1]*3600 + [int]$Matches[2]*60 + [int]$Matches[3]) * 1000
    }
    $w = 0; $h = 0
    if ($dim -match "(\d+)\s*x\s*(\d+)") { $w = [int]$Matches[1]; $h = [int]$Matches[2] }
    $fpsNum = 25; $fpsDen = 1
    if ($rate -match "(\d+)") {
      $f = [int]$Matches[1]
      if ($f -gt 0) { $fpsNum = $f; $fpsDen = 1000 }
    }
    return [pscustomobject]@{ ms=$ms; w=$w; h=$h; fpsNum=$fpsNum; fpsDen=$fpsDen; rate=48000; ch=2; lang="und" }
  } catch { return $null }
}

function Get-FfprobeMeta($file) {
  try {
    $json = & $ffprobe -v quiet -print_format json -show_format -show_streams "$($file.FullName)" | Out-String
    if ([string]::IsNullOrWhiteSpace($json)) { return $null }
    $data = $json | ConvertFrom-Json
    $v = $data.streams | Where-Object { $_.codec_type -eq "video" } | Select-Object -First 1
    $a = $data.streams | Where-Object { $_.codec_type -eq "audio" } | Select-Object -First 1
    $ms = [int]([double]$data.format.duration * 1000)
    $fpsNum = 25; $fpsDen = 1
    if ($v -and $v.r_frame_rate -match "^(\d+)/(\d+)$") { $fpsNum = [int]$Matches[1]; $fpsDen = [int]$Matches[2] }
    return [pscustomobject]@{
      ms    = $ms
      w     = if ($v) { [int]$v.width } else { 0 }
      h     = if ($v) { [int]$v.height } else { 0 }
      fpsNum= $fpsNum
      fpsDen= $fpsDen
      rate  = if ($a) { [int]$a.sample_rate } else { 48000 }
      ch    = if ($a) { [int]$a.channels } else { 2 }
      lang  = if ($a -and $a.tags -and $a.tags.language) { $a.tags.language } else { "und" }
    }
  } catch { return $null }
}

$count = 0
$excluded = 0
foreach ($root in $Folders) {
  if (-not (Test-Path $root)) { Write-Warning "Folder is not available: $root"; continue }
  Write-Host "Scanning: $root"
  Get-ChildItem -LiteralPath $root -Recurse -File -ErrorAction SilentlyContinue |
    Where-Object {
      $ok = $Extensions -contains $_.Extension.ToLower()
      if ($ok -and $ExcludeFolders) {
        foreach ($ex in $ExcludeFolders) {
          if ($_.FullName -like "*$ex*") { $ok = $false; break }
        }
      }
      if (-not $ok -and ($Extensions -contains $_.Extension.ToLower())) { $excluded++ }
      $ok
    } |
    ForEach-Object {
      $file = $_
      $meta = $null
      if ($useFfprobe) { $meta = Get-FfprobeMeta $file }
      if ($null -eq $meta -or $meta.ms -le 0) { $meta = Get-ShellMeta $file }
      if ($null -eq $meta) { return }
      $line = "{0};{1};{2};{3};{4};{5};{6};{7};{8};{9}" -f $file.FullName, $meta.ms, $file.Length, $meta.w, $meta.h, $meta.fpsNum, $meta.fpsDen, $meta.rate, $meta.ch, $meta.lang
      $rows.Add($line)
      $count++
      if ($count % 200 -eq 0) { Write-Host "  ... $count files" }
    }
}

$enc = New-Object System.Text.UTF8Encoding($true)
try {
  [System.IO.File]::WriteAllLines($Output, $rows, $enc)
} catch {
  $fallback = Join-Path ([Environment]::GetFolderPath("Desktop")) "biblioteka.csv"
  if ($fallback -eq $Output) { $fallback = Join-Path $env:TEMP "biblioteka.csv" }
  Write-Warning "Cannot write to $Output. Writing to $fallback"
  [System.IO.File]::WriteAllLines($fallback, $rows, $enc)
  $Output = $fallback
}
Write-Host ""
Write-Host "Done: $count files -> $Output" -ForegroundColor Green
if ($excluded -gt 0) { Write-Host "Excluded: $excluded files from ARHIVA KADRI" -ForegroundColor Yellow }
Write-Host "Upload this CSV in the application on the Library page."