Jump to content

Videos slow to start


Recommended Posts

IsJustaGhost
Posted

This has been a major frustration since I had first set up my server.

It's for personal use.
Server is ran on windows 10 pc. Media is stored on SATA HD connected directly to the motherboard the server is running on. Yet, it takes upwards of 30 seconds to start every video.  Videos that I can  play near instantly through VLC. This is horrendous when playing episodic videos. Besides the fact it will take the time to start the first video, when that ends, episode 2 will
eventually
start.

But it takes just as long, if not longer. 
It shows transcoding, yet I had disabled that in the user options. Though, the files should be able to play natively on both machines. At least, all the codecs are there. H264 mp4.

How can I speed up this process? 

One thought, which I can do nothing about is, to begin preloading next video when the play next button is visible.

 

 


 

embyserver.txt

Posted

Hello IsJustaGhost,

** This is an auto reply **

Please wait for someone from staff support or our members to reply to you.

It's recommended to provide more info, as it explain in this thread:


Thank you.

Emby Team

IsJustaGhost
Posted (edited)
37 minutes ago, Luke said:

HI, it could be related to the mp4 moov atom. Does this help:

https://superuser.com/questions/651074/mp4-takes-too-long-to-start

That would seam to effect videos played with any player. 
My videos start fine in VLC, Windows media player, movies and tv
All those common players.

 

Atom "©too" contains: Lavf56.40.101

No idea what that is.

 

What's really confusing is, this delay happens if even played from the server pc.

Edited by IsJustaGhost
Posted
10 hours ago, IsJustaGhost said:

That would seam to effect videos played with any player. 
My videos start fine in VLC, Windows media player, movies and tv
All those common players.

 

Atom "©too" contains: Lavf56.40.101

No idea what that is.

 

What's really confusing is, this delay happens if even played from the server pc.

No it wouldn't necessarily affect every player, not when VLC has direct file access and can grab different chunks of the file quickly. Streaming is different, and its' the placement of the moov atom that allows video to start quickly.

If it's taking a long time to start on the local network, then most likely this means that the moov atom is not there, and therefore the browser video player has to fetch the entire contents of the file before it can start playing.

I would try reencoding one of these mp4's and see how things compare.

IsJustaGhost
Posted
9 hours ago, Luke said:

No it wouldn't necessarily affect every player, not when VLC has direct file access and can grab different chunks of the file quickly. Streaming is different, and its' the placement of the moov atom that allows video to start quickly.

If it's taking a long time to start on the local network, then most likely this means that the moov atom is not there, and therefore the browser video player has to fetch the entire contents of the file before it can start playing.

I would try reencoding one of these mp4's and see how things compare.

I obviously do not understand any of that.

Using Powershell to prepare for automation

-- Based no example in the above link.
Made audio choppy
ffmpeg -i $_.FullName -c:v libx264 -c:a aac -strict experimental -b:v 1M -b:a 128k -movflags frag_keyframe+empty_moov $output

-- To speed up the process by keeping original audio and video and, to prevent audio breakage. I don't know if this will actually fragment the frames at all.
ffmpeg -i $_.FullName -acodec copy -vcodec copy -strict experimental -b:v 1M -b:a 128k -movflags frag_keyframe+empty_moov $output

Neither improved or changed the start delay.

  • 2 weeks later...
Posted

If you remux to mkv and try to play in Chrome, how does that compare?

IsJustaGhost
Posted
On 9/12/2024 at 11:01 AM, Luke said:

If you remux to mkv and try to play in Chrome, how does that compare?

Thank you for all the responses. I ended up creating a somewhat complex Powershell script for full automation. I tried using Handbreak but, it was turning out too slow as it required reencoding every video.

My script simply adds the faststart flag to every video it is not applied to. then replaces the the original video with the output video. Then appending an additional datastream to the file to store a custom faststart flag to, in order to speed up future run times without modifying additional data or ed3 tags. As it will skip previously processed videos.  

Placed in the root media directory, it will reursivly scan for mp4 files, which can be change on the the line. "Get-ChildItem $path -Recurse -Include '*.mp4' | Foreach {"
More extensions can be added.

I have not fully tested this out yet. I have ran it a few time during writing. Just  not watched every video processed yet.

I use it for a structure of..
root\series\S1E01.mp4
root\series\season 1\S1E01.mp4

If anyone else wanted to try it out, or improve on it.

Quote

 

cls

# The "Tag data stream" is used to append the faststart to the file data in a separate stream to speed up
# processing by excluding files already processed.

# Author of Add-TagStream Jeff Hicks url "https://jdhitsolutions.com/blog/scripting/8888/friday-fun-with-powershell-and-alternate-data-streams/"
# Author of Get-TagStream Jeff Hicks url "https://jdhitsolutions.com/blog/scripting/8888/friday-fun-with-powershell-and-alternate-data-streams/"

Function Add-TagStream {
    [cmdletbinding(SupportsShouldProcess)]
    Param(
        [Parameter(
            Position = 0,
            Mandatory,
            ValueFromPipeline,
            ValueFromPipelineByPropertyName,
            HelpMessage = "Specify a file path."
        )]
        [ValidateScript({ (Test-Path $_) -AND ((Get-Item $_).psprovider.name -eq 'FileSystem') })]
        [Alias("fullname")]
        [string[]]$Path,
        [parameter(Mandatory, HelpMessage = "Specify a set of tags")]
        [alias("tag")]
        [string[]]$Value,
        [Parameter(HelpMessage = "Specify the name of the Tags stream. The default is 'tags'.")]
        [string]$Stream
    )
    Begin {
        Write-Verbose "[$((Get-Date).TimeofDay) BEGIN  ] Starting $($myinvocation.mycommand)"
        if (-Not ($psboundparameters.containskey["Stream"])) {
            $psboundparameters.Add("Stream", "tags")
        }
    } #begin

    Process {
        Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Adding Tags $($value -join ',') to stream $($psboundparameters['Stream']) in $Path"
        Set-Content @psboundparameters
    } #process

    End {
        Write-Verbose "[$((Get-Date).TimeofDay) END    ] Ending $($myinvocation.mycommand)"
    } #end

} #close Add-Tagstream

Function Get-TagStream {
    [cmdletbinding()]
    Param(
        [Parameter(
            Position = 0,
            Mandatory,
            ValueFromPipeline,
            ValueFromPipelineByPropertyName,
            HelpMessage = "Specify a file path."
        )]
        [ValidateScript({ (Test-Path $_) -AND ((Get-Item $_).psprovider.name -eq 'FileSystem') })]
        [Alias("fullname")]
        [string[]]$Path,

        [Parameter(HelpMessage = "Specify the name of the tag stream. The default is 'tags'")]
        [string]$Stream
    )
    Begin {
        Write-Verbose "[$((Get-Date).TimeofDay) BEGIN  ] Starting $($myinvocation.mycommand)"
        $splat = @{
            ErrorAction = "Stop"
        }

        if ($psboundparameters.containskey["Stream"]) {

            $splat.Add("Stream", $psboundparameters["Stream"])
        }
        else {
            $splat.Add("Stream", "tags")
        }
    } #begin

    Process {
        foreach ($item in $path) {
            $splat['Path'] = Convert-Path $item
            Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Getting tags stream $($splat['Stream']) from $item"
            Try {
                $info = Get-Content @splat
                [pscustomobject]@{
                    Path       = $splat.path
                    Tags = $info
                }
            }
            Catch {
                #Write-Warning "The stream $($splat['Stream']) was not found on $path"
            }
        }
    } #process

    End {
        Write-Verbose "[$((Get-Date).TimeofDay) END    ] Ending $($myinvocation.mycommand)"
    } #end

} #close Get-TagStream

$rootTemp = [System.IO.Path]::GetTempPath()

if (Test-Path (Join-Path $rootTemp 'vid-faststart')){
    Remove-Item (Join-Path $rootTemp 'vid-faststart') -ErrorAction Continue -Recurse
}
# Create a subfulder in the temp directory to use for storing converted videos.
$TEMP = New-Item -ItemType Directory -Path (Join-Path $rootTemp 'vid-faststart')
$TEMP

$seriesData = @()
$path = $PSScriptRoot

$filecount = 0
$n = 0

$videos = Get-ChildItem $path -Recurse -Include '*.mp4' | Foreach {
    $_
}

$numVideos = $videos.count
$i = 0
Get-ChildItem $path -Recurse -Include '*.mp4' | Foreach {

    $status = 'Episode :' + $_.index
    $progress = ($i / $numVideos) * 100
    $progress = [Math]::Round($progress,2)

    $status = $_.FullName
    
    if(!($_ | Get-TagStream | Select-String 'faststart' )){
        $result = (ffprobe -v debug $_.Fullname 2>&1 | Select-String -Pattern "seeks:1")
        $faststart = $result -ne $null
        if(!($faststart)){
            $filecount++
            $status = 'Added ' + $_.FullName
            $root = split-path $_.Directory -Parent

            $root = split-path $_.Directory -Parent
            $serieName = split-path $root -leaf
            if($serieName -eq (split-path $path -leaf)){
                $serieName = split-path $_.Directory -leaf
                $root = $_.Directory
            }

            if($serieName -ne $lastSerieName){
                $lastSerieName = $serieName
                $n = 1
            } else {
                $n++
            }

            if($seriesData | Where-Object {$_.Name -eq "$serieName"}){
            } else {
                $seriesData += New-Object PsObject -Property @{
                    Name = $serieName;
                    fullName = $root.FullName;
                    VideoData = @();
                }
            }

            $videoData = ($seriesData | Where-Object {$_.Name -eq "$serieName"}).VideoData
           # Write-Host ($videoData | Select-Object Name)
            $_ | Add-Member -MemberType NoteProperty -Name 'SerieName' -Value $SerieName
            $_ | Add-Member -MemberType NoteProperty -Name 'index' -Value $n
            $videoData += $_
         #   Write-Host $videoData
            #$VideoData | Select-Object SerieName,name
            #$_

            ($seriesData | Where-Object {$_.Name -eq "$serieName"}).VideoData =  $videoData
        } else {
            $status = 'Skipped ' + $_.FullName
        
            $_ | Add-TagStream -tag 'faststart'
        }
    }
#    Write-Host 'root ' $root
    
    $activity = 'Files added to be proccessed ' + $filecount.ToString()
    Write-Progress -Activity $activity -Status $status -PercentComplete $progress

    $i++
}
Write-Progress -Completed -Activity 'Completed'
cls
$i = 0
$numSeries = $seriesData.count
$seriesData | Foreach {

    $activity = "Searies: " + $_.name
    
    $status = 'Episode :' + $_.index
    $progress = ($i / $numSeries) * 100
    $progress = [Math]::Round($progress,2)

    Write-Progress -id 1 -Activity $activity -Status $status -PercentComplete $progress
    
    $esodes = $_.videoData.count
    $parent = $_
    $parent.videoData | Foreach {
        $status = 'Episode :' + $_.index

        $progress = ($_.index / $esodes) * 100
        $progress = [Math]::Round($progress,2)
        Write-Progress -ID 2 -Activity $_.name -Status $status -PercentComplete $progress

        $tempPath = $TEMP.FullName + '\' + $parent.Name
        
        if(!(Test-Path $tempPath)) {
            New-Item -ItemType Directory -Path $tempPath
        }
        $outfile = $tempPath + '\' + $_.name
        Write-Host '- outfile ' $outfile

        ffmpeg -i $_.fullname -map 0 -c copy -c:a:1 ac3 -b:a:1 -o $outfile -movflags faststart -hide_banner -loglevel error

        Move-Item -Path $outfile -Destination $_.Directory -Force
        Get-Item $_.FullName | Add-TagStream -tag 'faststart'
    }
    
    $i++
}

Remove-Item $TEMP -ErrorAction Continue -Recurse

 

 

visproduction
Posted

IsJusta,


Handbreak will ask by default to reencode.  You only may need remuxing, which pretty much just fixes the metadata without reencoding.  Usually, you just select save original audio and video and then make a copy.  Today's computers would take probably 20 seconds to do it for a 2 hour media.  ffmpeg and many other 3rd party software can do similar remuxing and fix errors.  I think even VLC can do a good job, but VLC takes like 20 clicks.  I use Windows software AVIdemux and just copy video and audio.  A lot of people in the forum like MKVtools.  

Don't reencode, just do remuxing and copy.  Try Handbreak, if you know that sofware.  Set video and audio to copy original.  The new copy of media might get fixed and solve the problem.

Hope that helps.

IsJustaGhost
Posted
1 hour ago, visproduction said:

IsJusta,


Handbreak will ask by default to reencode.  You only may need remuxing, which pretty much just fixes the metadata without reencoding.  Usually, you just select save original audio and video and then make a copy.  Today's computers would take probably 20 seconds to do it for a 2 hour media.  ffmpeg and many other 3rd party software can do similar remuxing and fix errors.  I think even VLC can do a good job, but VLC takes like 20 clicks.  I use Windows software AVIdemux and just copy video and audio.  A lot of people in the forum like MKVtools.  

Don't reencode, just do remuxing and copy.  Try Handbreak, if you know that sofware.  Set video and audio to copy original.  The new copy of media might get fixed and solve the problem.

Hope that helps.

I did not see anything in Handbreak for copying video. Every step required re-enocding. The only option was audio passthrough. I did searches online that all resulted in saying the same thing.  My script above, it's longest step is the ffprobe used to check a file for faststart. The ffmpeg just sets that flag to the video leaving audio and video alone. So, the ffprobe takes longer per file, though, not as long as Handbreak did to load up a source. And, making it use additional data streams to store a flag makes it only scan files that have yet to be optimized with faststart. Not exactly sure how those data streams work, I actually found out about them an hour before I posted the script here. But, from what I've read, It attaches the data to the ntsf file as long as it's not moved. So, I tag files that are found to pass the ffprobe where they are and, do the same on newly completed files after I move the ffmpeg output to the original location. 

visproduction
Posted (edited)

The command line ffmpeg may need a full ffmpeg install.  I found this:

ffmpeg -i input.mkv -c copy output.mp4

See: https://www.reddit.com/r/PleX/comments/qhe0ap/trying_to_use_ffmpeg_to_remux_mkv_to_mp4/?rdt=39482
https://docs.tdarr.io/blog/how-to-remux-or-change-a-file-container-using-ffmpeg/

I really like AVIDemux much more than Handbreak, because Handbreak sort of forces you into preset average settings that I really don't like.  You have to really click all over the place to get around these settings.  For example, handbreak forces an aspect ratio change to widescreen that equals 2.37.  Well, that is wrong.  The change is either 2.35 or 2.39.  Handbreak picked the average and hope that most people will never notice the difference.  Yes, perhaps that is true, but it means that any film grain that might be in the media will get blurred and I can see the difference.

AVIDemux easily sets to copy video and copy audio,  It will, however, strip away all titles, chapters and subtitles from any media if you are converting to .mp4 h.264, which is the only one I use anyway.  When I am done getting the quality I like, using video h.264 and audio AAC, the result will play fine on anyone's hardware.  No transcoding is needed as long as your quality encode to around no more than 2400 kbps for 1080P. Using this software, you may need to use other software to pull out subs if you need them into .srt files.  Anyway, that's beside the point for the issue in this post.  Remux with AVIDemux finishes in 20 seconds for 2 hour 1080P.  Try this software instead of Handbreak or play with ffmpeg command line.  If you have original mp4 h.264, you can use command line with MP4box app.

Hope that helps.

 

Edited by visproduction

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...