Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Скриптовые языки администрирования Windows (http://forum.oszone.net/forumdisplay.php?f=102)
-   -   Запуск FFprobe на Powershell (http://forum.oszone.net/showthread.php?t=342990)

Uragan66 18-11-2019 13:30 2896983

Запуск FFprobe на Powershell
 
Добрый день всем!
Пытаюсь посредством FFProbe получить информацию о потоках iptv от провайдера.
Хочу это сделать скриптом PS, но запуская таким кодом:
Код:

$soft = 'ffprobe.exe'
Get-Content .\log\Test-streams.ini `
| ForEach {Start-Process -FilePath $soft -ArgumentList "-hide_banner -show_streams -timeout 500000 $_ -report" -NoNewWindow -Wait}

получаю n-е количество логов, а не один, как хотелось бы.
Хотя это исправляется легко путём объединения логов. Вопрос в другом, при запуске ffprobe с ключом -report не воспринимаются кириллические символы в ответе сервера. В итоге в логах, где есть русские названия, получаются кракозябры.
Дальнейшая смена кодировки ничего не даёт.
Подскажите, пожалуйста, есть ли способ запуска ffprobe на PS, чтобы нормальный лог/логи были на выходе ?

P.S. И попутный, пока нерешенный вопрос: есть ли способ запуска ffprobe на PS или CMD в многопоточном или лучше асинхронном режиме ?

DJ Mogarych 18-11-2019 22:07 2897097

Цитата:

Цитата Uragan66
Хотя это исправляется легко путём объединения логов »

Можно get-content .\log\ffprobe-*.log

Цитата:

Цитата Uragan66
кириллические символы в ответе сервера »

Может быть, поможет экспорт в какой-нибудь другой формат, типа xml, там вроде UTF8 по умолчанию. Примеры в статье:
https://www.bugcodemaster.com/articl...on-video-files

Uragan66 18-11-2019 22:33 2897102

DJ Mogarych, спасибо, посмотрю по ссылке. Пока решилось всё "костылём" с CMD.
Цитата:

Цитата DJ Mogarych
Можно get-content .\log\ffprobe-*.log »

да, так и объединяю...
*****************
Сейчас больше интересует вопрос многопоточного или ассинхронного запуска FFprobe. Возможно ли это на ps или cmd ?
А то слишком долго FFprobe работает, к примеру, с 225 ссылками.

DJ Mogarych 19-11-2019 09:07 2897127

Как вариант - поделить 225 ссылок на части и запускать ffprobe для каждой части отдельно.

Uragan66 20-11-2019 19:31 2897323

Цитата:

Цитата DJ Mogarych
Как вариант - поделить 225 ссылок на части »

DJ Mogarych, думал я так сделать, но не могу понять как несколько потоков ffprobe запустить одним кодом.
Пробовал так:
Код:

Get-Content .\log\Test-streams.ini `
| ForEach {Start-Job -ScriptBlock {
  & ffprobe.exe -timeout 6000000 -hide_banner -select_streams v:1 -print_format json=compact=1 -show_entries format=filename -show_programs -show_entries program=service_name -of default=noprint_wrappers=1:nokey=0 $_ >>out.json
}}

Вывода никакого нет, да и ffprobe вроде вообще не запускается.
Знаю, что результаты фоновых заданий Start-Job можно получить командлетом Receive-Job, но как правильно код составить и, главное, заставить ffprobe работать, пока не могу сообразить.

DJ Mogarych 20-11-2019 22:16 2897343

Можно сделать 4 задачи в стандартном планировщике задач.

Uragan66 08-12-2019 12:48 2899489

Добрый день всем!
Цитата DJ Mogarych:
Можно сделать 4 задачи в стандартном планировщике задач. »
DJ Mogarych, ну это немного не то, не каждый умеет использовать планировщик, а скрипт планируется для нескольких пользователей, да и не совсем удобно это...
Нашел интересный скрипт многопоточного запуска пинга - https://xaegr.wordpress.com/2011/07/12/threadping/
Попробовал его переделать под свою задачу:
Код:

Param (
[string[]]$unc = 'http://109.248.67.1:4044',
[string[]]$prt = ':1234',         
[string[]]$Address = $(1..20 | %{"$unc/udp/239.195.1.$_$prt"}),           
[int]$Threads = 3           
)           
           
write-host "Distributing addresses around jobs"           
$JobAddresses = @{}           
$CurJob = 0           
$CurAddress = 0           
while ($CurAddress -lt $Address.count)           
{           
    $JobAddresses[$CurJob] += @($Address[$CurAddress])           
    $CurAddress++           
    if ($CurJob -eq $Threads -1)           
    {           
        $CurJob = 0           
    }           
    else           
    {           
        $CurJob++           
    }           
}           
           
$Jobs = @()           
foreach ($n in 0 .. ($Threads-1))           
{           
    Write-host "Starting job $n, for addresses $($JobAddresses[$n])"           
    $Jobs += Start-Job -ArgumentList "ffprobe.exe -timeout 6000000 -hide_banner -select_streams v:1 -print_format json=compact=1 -show_entries format=filename -show_programs -show_entries program=service_name -of default=noprint_wrappers=1:nokey=0 $JobAddresses[$n] >>out.json" -ScriptBlock {
cmd /c
}           
}           
           
write-host "Waiting for jobs"           
$ReceivedJobs = 0           
while ($ReceivedJobs -le $Jobs.Count)           
{           
    foreach ($CompletedJob in ($Jobs | where {$_.State -eq "Completed"}))           
    {           
        Receive-Job $CompletedJob | select status, address, roundtriptime           
        $ReceivedJobs ++           
        sleep 1           
    }           
}           
           
Remove-Job $Jobs           
write-host "Done."

Но последний блок кода (вывод) никак не получается... Да и ffprobe не знаю как точно запустить с помощью Start-Job
Может кто сможет помочь с этим скриптом, буду очень благодарен.

DJ Mogarych 09-12-2019 09:14 2899600

Истина где-то здесь: https://www.google.com/search?q=ffmp...simultaneously

Uragan66 09-12-2019 23:57 2899713

DJ Mogarych, спасибо большое, просмотрел несколько ссылок, но так и не смог что-либо применить к своему коду.
Но решение всё же найдено. На social.technet.microsoft.com предложили такой код (за что большая благодарность Vector BCO ) :
Код:

$i = 0
foreach ($OL in @(1..255)){ # 1 foreach вместо 2х и тем более 3х
    Start-Job -Name ffprobe -ArgumentList $OL -ScriptBlock {
        $OL = $args[0]
        $URI = "http://79.105.135.20:5055/udp/239.28.0.$OL`:2020
        $soft = 'C:\full\path\to your program\ffprobe.exe' # Полный путь, или можно пробовать играться с переменной $Path. Для начала я бы не заморачивался со вторым
        $utf8 = [System.Text.Encoding]::GetEncoding(65001)
        cmd /c $utf8.GetString($utf8.GetBytes("$soft -timeout 6000000 -hide_banner -select_streams v:1 -print_format json=compact=1 -show_entries format=filename -show_programs -show_entries program=service_name -of default=noprint_wrappers=1:nokey=0 $URI >> C:\temp\out_$OL.json")) # И снова полный путь
    }

    # Если запустить 255 потоков, то производительность сильно просядет (скорее всего)
    # По этому мое предложение запускать по 5 задач, ждать их выполнения, после чего запускать следующие 5 задач. При желании можете увеличить до 10 или 15
    if (($i -ge 5) -or ($OL -eq 255){
        Get-Job ffprobe | Wait-Job -Timeout 300
        Get-Job ffprobe | Receive-Job
        Get-Job ffprobe | Remove-Job -Force
        $i = 0
    } else {$i++}
}

Пришлось немного повозиться с жесткой привязкой путей, но всё получилось, как было нужно.


Время: 18:15.

Время: 18:15.
© OSzone.net 2001-