News:

--

Main Menu

A changing resolution video file

Started by jimmyjim, February 20, 2022, 07:51:10 AM

Previous topic - Next topic

jimmyjim

Hi guys,
I have a video file which changes resolutions


Does anyone know a way to turn this single file into multiple files (for example a 960x540 video file and a 1280x720) using avid or ffmpeg so I can edit it?

Thanks

eumagga0x2a

Close Avidemux, delete the generated .idx2 index file and let Avidemux re-index the video. In admlog.txt from %localappdata%\avidemux\ directory, you will find one of more lines with "Size change" text. Note the hexadecimal value of offset where the change occurs. You need to split the MPEG-TS stream file at these offsets into separate files using a simple utility like head or dd which doesn't care about file content at all, then load/append matching file sets in Avidemux as separate videos.

I don't think ffmpeg will help here, but I may be wrong.

jimmyjim

#2
Hello guys,
I did read and appreciate your response all those months ago eumagga0x2a.
I didn't know much about video formats at the time and still dont.
Recently had to tackle this problem, I was able to cut videos using ffprobe to find out where the changes occur using this command (for anyone else interested) to get the keyframes:

ffprobe -hide_banner -skip_frame nokey -show_streams -select_streams v -show_entries frame=width,height,best_effort_timestamp_time -of json=compact=1 input.mp4

and ffmpeg to cut the vid (comes with problems, some of the cuts need re-encoding it seems) so I could edit the video (now videos with the same dimensions can be edited together) with avidemux.
I needed a simple drag and drop solution (loads of videos to edit) so I have a powershell script; i dont mind sharing if anyone else is interested.
Surprised this isn't more of a problem (videos changing resolution; e.g. when someone rotates their phone the resolution changes when recording a video?) worth tackling.

Are there other possible automated solutions?
I suppose I could just resize the whole video to the max resolution but it's not ideal.
Thanks!

eumagga0x2a

Quote from: jimmyjim on September 17, 2022, 06:40:19 AMvideos changing resolution; e.g. when someone rotates their phone the resolution changes when recording a video?

Resolution doesn't change when a smartphone is rotated. Rotation state is only recorded in video metadata (ignored by Avidemux).

So far, no advances regarding handling of videos with variable dimensions in Avidemux compared to the state of affairs I described above.

shmorgasbored773

>>I needed a simple drag and drop solution (loads of videos to edit) so I have a powershell script; i dont mind sharing if anyone else is interested.<<

I'd be very intersected in the script. I have several recordings of streams where the aspect ratio changes at the commercials.


jimmyjim

#5
Quote from: shmorgasbored773 on December 24, 2023, 03:09:35 AM>>I needed a simple drag and drop solution (loads of videos to edit) so I have a powershell script; i dont mind sharing if anyone else is interested.<<

I'd be very intersected in the script. I have several recordings of streams where the aspect ratio changes at the commercials.

This usually works pretty well, rename the file to clipRes.ps1 or something
clipRes "file1.ts", "file2.ts"
edit: i dont think the attachment can be downloaded? here it is:
function launchProcess{
    Param(
        [String]$pathToExe,
        [Object]$processargs
        )
        Process{
        $ProcessInfo = New-Object System.Diagnostics.ProcessStartInfo
        $ProcessInfo.FileName = $pathToExe
        $ProcessInfo.RedirectStandardError = $true
        $ProcessInfo.RedirectStandardOutput = $true
        $ProcessInfo.UseShellExecute = $false
        $ProcessInfo.Arguments = $processargs
        #$processinfo.CreateNoWindow=$true
        $Process = New-Object System.Diagnostics.Process
        $Process.StartInfo = $ProcessInfo
        $Process.Start() | Out-Null

        $Process    #return the process
        }
}

function getFrameData{
    Param(
        [String]$pathToVid
    )
    Process{
        $fileName=[System.IO.Path]::GetFileNameWithoutExtension($pathToVid)
        $fileDataPath=[System.IO.Path]::GetDirectoryName($pathToVid)+"\$fileName.json"
        if([System.IO.File]::Exists($fileDataPath)){
            $data= Get-Content $fileDataPath | convertfrom-json
        }
        else {
            write-host "Gathering key frame info"

            $processargs=@("-hide_banner", "-skip_frame", "nokey", "-show_streams", "-select_streams", "v", "-show_entries", "frame=width,height,best_effort_timestamp_time", "-of", "json=compact=1", "", """$pathToVid""")
            $Process=launchProcess $pathToFFProbeExe $processargs
            $data=$Process.StandardOutput.ReadToEnd() | ConvertFrom-Json

            # add a property for the clips that will be generated
            $data | Add-Member -name 'clips' -Value @() -MemberType NoteProperty
            $data | Add-Member -name 'saved' -Value $false -MemberType NoteProperty
            $data | Add-Member -name 'fileDataPath' -Value $fileDataPath -MemberType NoteProperty
        }

        $data
    }
}

function cutVideo{

    Param(
        [String]$sourceFile,
        [String]$outputFile,
        [double]$startTime,
        [Object]$endTime,
    [int]$width,
    [int]$height
        )   

    Process{
        $params=@("-hide_banner","-loglevel", "error","-ss", "$startTime","-to", "$endTime", "-i", """$pathToVid""")

        $params+=@("-aspect", "$($width):$($height)")
    $params+=@("-c", "copy")

        $params+="""$outputFile"""

    $process=start-process $pathToFFMpegExe -PassThru -ArgumentList $params -NoNewWindow
        #($process=start-process $pathToFFMpegExe -PassThru -ArgumentList $params -NoNewWindow).PriorityClass = [System.Diagnostics.ProcessPriorityClass]::BelowNormal
        #$process.ProcessorAffinity=0x3
        Wait-Process -inputobject $process
    }
}

function Get-Clips{
    Param(
        [Object]$data
    )
    Process{
        $newResFrame=[PSCustomObject]@{
            best_effort_timestamp_time=0#$data.frames[0].best_effort_timestamp_time
            height=$data.streams[0].height
            width=$data.streams[0].width
        }
        $count=0
        while($count -lt $data.frames.count){
            $frame=$data.frames[$count]
            if(($frame.width -ne $newResFrame.width `
            -and $frame.height -ne $newResFrame.height) -or ($count+1)-eq$data.frames.count){

                $lastFrame=$null;    #the last frame
                if(($count+1)-ne$data.frames.count){
                    # not at the end of the file, so check the non key frames for the change of size
                    <#$startInt=$data.frames[$count-1].best_effort_timestamp_time
                    $secondsToCheck=$frame.best_effort_timestamp_time-$startInt
                    $processargs=@("-hide_banner", "-show_streams", "-select_streams", "v", "-show_entries", "frame=width,height,best_effort_timestamp_time", "-read_intervals", "$startInt%+$secondsToCheck","-of", "json=compact=1", "", """$pathToVid""")
                    $Process=launchProcess $pathToFFProbeExe $processargs
                    $datal=$Process.StandardOutput.ReadToEnd() | ConvertFrom-Json

                    $lastFrame=$datal.frames[-2]

                    #look for the time it changes
                    foreach($item in $data){
                        if($item.width -ne $newResFrame.width -and $item.height -ne $newResFrame.height){
                            $lastFrame=$item
                            break
                        }
                    }#>
                    $lastFrame=$data.frames[$count-2]
                }
                else{
                    $lastFrame=$data.frames[-1]
                }

                # save so we dont do this loop again if we reload
                $data.clips+=[PSCustomObject]@{
                    height=$newResFrame.height
                    width=$newResFrame.width
                    startTimestamp=$newResFrame.best_effort_timestamp_time
                    endTimeStamp=$lastFrame.best_effort_timestamp_time
                }

                $newResFrame=$frame
            }

            ++$count
        }
    }
}

$pathToFFMpegExe=&where.exe ffmpeg
$pathToFFProbeExe=$pathToFFMpegExe.replace("ffmpeg.exe", "ffprobe.exe")
$outputExt="ts"

if($args[0] -eq ""){exit}

$files=$args[0] -split ", "


foreach($file in $files){
    $pathToVid=$file
    $fileName=[System.IO.Path]::GetFileNameWithoutExtension($pathToVid)

    $data=getFrameData -pathToVid $pathToVid


    # sort the video into clips of same res
    if($data.clips.Count -eq 0){
        Get-Clips -data $data
    }

    if($data.clips.Count -eq 1){
        write-host "1 clip found, skipping"
    }
    else{
        Write-Host $data.clips.Count"clips being created"

        $count=0
        while($count -lt $data.clips.Count){
            $widthHeightStr=""
            if($data.clips[$count].width -ne $data.streams[0].width `
            -and $data.clips[$count].height -ne $data.streams[0].height){
                $widthHeightStr=" $($data.clips[$count].width)x$($data.clips[$count].height)"
            }
            $outputFile=[System.IO.Path]::GetDirectoryName($pathToVid)+"\"+"$fileName $($count+1)$widthHeightStr.$outputExt"

            $endTime=$data.clips[$count].endTimeStamp

            cutVideo -sourceFile $pathToVid -outputFile $outputFile -startTime $data.clips[$count].startTimestamp -endTime $endTime -width $data.clips[$count].width -height $data.clips[$count].height

            ++$count
        }
    }

    if($data.saved -ne $true){
        $data.saved=$true
        $data | convertto-json -WarningAction SilentlyContinue | out-file -filepath $data.fileDataPath
    }
}

You can drag files onto this .bat if you name it the same as the powershell script, e.g. clipRes.ps1 and clipRes.bat instead of typing
@echo off
rem the name of the script is drive path name of the Parameter %0
rem (= the batch file) but with the extension ".ps1"
set PSScript=%~dpn0.ps1
set args=%1
:More
shift
if '%1'=='' goto Done
set args=%args%, %1
goto More
:Done
pwsh -NoExit -Command "& '%PSScript%' '%args%'"

eumagga0x2a

Regarding download of attachments: The server the forum runs on doesn't work with http2. Disable the protocol (AKA spdy) via the advanced settings of Firefox. I am not aware of other browsers allowing to do that.