批处理之家's Archiver

nwm310 发表于 2019-11-22 16:42

PowerShell实现Win10 影片截圖

[i=s] 本帖最后由 nwm310 于 2019-11-23 19:41 编辑 [/i]

11.23修正:檔名 & 的問題
===

把ps1 放到影片旁邊
對著ps1按右鍵 → 用 PowerShell 執行

[b][color=Sienna]Win10 適用[/color][/b]

getMp4Pic 用法
[quote]#預設值:從 0:0:0 開始截圖,截圖到結束,間隔 0:1:0  一分鐘
getMp4Pic 'C:\3.mp4'  -start 0 -end -1 -step 0:1:0 -w 0 -h 0

#效果同上。可省略其他參數。
getMp4Pic  'C:\3.mp4'


#只截一張圖 0:0:5
getMp4Pic 'C:\3.mp4'  0:0:5   0:0:5

#從 0:0:5 開始截圖,截圖到結束,間隔 0:0:30 三十秒
getMp4Pic 'C:\3.mp4'   0:0:5   -step  0:0:30

#從 0:0:5 開始截圖,截圖到0:3:0,間隔 0:1:0 一分鐘
getMp4Pic 'C:\3.mp4'  0:0:5   0:3:0

#從 0:0:5 開始截圖,截圖到0:3:0,間隔 0:0:20 二十秒
getMp4Pic 'C:\3.mp4'  0:0:5   0:3:0  0:0:20

#設定長度、寬度
getMp4Pic 'C:\3.mp4'  0:0:5   0:3:0  0:0:20 -w 640 -h 480 [/quote]

[b][color=Red][size=5]第33行、第39行:前面不能有空格[/size][/color][/b][code]
function getMp4Pic{
    param(
        [io.fileinfo]$mp4,
        [timespan]$startTime = '0:0:0' ,
        [timespan]$endTime = '-1' ,
        [timespan]$step = '0:1:0' ,
        [uint32]$width = 0 ,
        [uint32]$height = 0
    )
    #learn from https://fleexlab.blogspot.com/2018/02/using-winrts-iasyncoperation-in.html
    Add-Type -AssemblyName System.Runtime.WindowsRuntime
    $asTaskGeneric = ([System.WindowsRuntimeSystemExtensions].GetMethods() |
        ? { $_.Name -eq 'AsTask' -and $_.GetParameters().Count -eq 1 -and
        $_.GetParameters()[0].ParameterType.Name -eq 'IAsyncOperation`1' }   )[0]
    Function Await($WinRtTask, $ResultType) {
    $asTask = $asTaskGeneric.MakeGenericMethod($ResultType)
    $netTask = $asTask.Invoke($null, @($WinRtTask))
    $netTask.Wait(-1) | Out-Null
    $netTask.Result
    }


    #http://blog.bagusandryan.com/get-video-thumbnail-storagefile-uwp-732/
    #https://docs.microsoft.com/en-us/windows/uwp/audio-video-camera/imaging

    [Windows.Storage.StorageFile , Windows.Storage , ContentType=WindowsRuntime] > $null
    [Windows.Media.Editing.MediaComposition , Windows.Media.Editing , ContentType=WindowsRuntime] > $null
    [Windows.Graphics.Imaging.ImageStream , Windows.Graphics.Imaging , ContentType=WindowsRuntime] > $null

    $xmlPath = Join-Path  $mp4.DirectoryName  "MediaClip11111xml.xml"
    $mp4PathInXml = "$mp4"  -replace  '&','&'
@"
<?xml version="1.0" encoding="UTF-8"?>
<Composition>
<Clips>
    <MediaClip Path="$mp4PathInXml" />
</Clips>
</Composition>
"@ | sc -Literal  $xmlPath  -Enc UTF8
# "@  must at begin of line
    $a = [Windows.Storage.StorageFile]
    $xmlFile = await ($a::GetFileFromPathAsync($xmlPath)) ($a)

    #===== MediaComposition =====
    $a = [Windows.Media.Editing.MediaComposition]
    $m01 = await ($a::LoadAsync($xmlFile)) ($a)

    $NearestKeyFrame = 1
    if ($endTime -eq '-1'){ $endTime = $m01.Clips.OriginalDuration }

    $outFolder = Join-Path $mp4.DirectoryName  ($mp4.BaseName + "_$startTime" -replace ':','_')
    md $outFolder 2>$null >$null
    for ($time = $startTime; $time -le $endTime; $time += $step){
        $a = [Windows.Graphics.Imaging.ImageStream]
        $mp4Thumb = await ($m01.GetThumbnailAsync($time, $width, $height, $NearestKeyFrame)) ($a)

        $reader = [Windows.Storage.Streams.DataReader]::new($mp4Thumb.GetInputStreamAt(0))
        $reader.LoadAsync($mp4Thumb.Size) > $null
        $bytes = new-object byte[] ($mp4Thumb.Size)
        $reader.ReadBytes($bytes)
        
        #out
        $outName = $mp4.BaseName + ("_$time" -replace ':','_') + '.jpg'
        $outPath = Join-Path $outFolder  $outName
        [System.IO.File]::WriteAllBytes($outPath, $bytes)
    }

    del $xmlPath
}
#=======

cd -literal $PSScriptRoot
[Environment]::CurrentDirectory = pwd
$files = @(dir *.mp4,*.mkv -file)
if ($files.count -ne 0){
    getMp4Pic  $files[0]  -start 0:0:5  -end 0:0:5  # -step 0:0:20 -w 640 -h 480
}


[/code]

页: [1]

Powered by Discuz! Archiver 7.2  © 2001-2009 Comsenz Inc.