Welcome to Doom9's Forum, THE in-place to be for everyone interested in DVD conversion.

Before you start posting please read the forum rules. By posting to this forum you agree to abide by the rules.

 

Go Back   Doom9's Forum > Capturing and Editing Video > VapourSynth

Reply
 
Thread Tools Search this Thread Display Modes
Old 13th August 2022, 19:19   #1  |  Link
MysteryX
Soul Architect
 
MysteryX's Avatar
 
Join Date: Apr 2014
Posts: 2,559
How to trim audio

How can I trim the audio in VapourSynth?

Code:
clip = core.lsmas.LibavSMASHSource(source)
audio = vs.core.bas.Source(source, track=-1)
clip = clip.std.Trim(first = startpos * clip.fps, length = length * clip.fps)
#audio = audio.std.TrimAudio(first = startpos * clip.sample_rate, length = length * clip.sample_rate)
"AudioTrim performs exactly the same operation on audio clips but the unit is obviously samples instead of frames."

It's really not clear what that means or how I should write it. I think the audio documentation really could be improved.
MysteryX is offline   Reply With Quote
Old 13th August 2022, 20:00   #2  |  Link
_Al_
Registered User
 
Join Date: May 2011
Posts: 321
most simple and transparent seems to be something:
Code:
import math
def to_samples(frame, fps=clip.fps, samplerate=48000):
    return math.floor((samplerate/fps)*frame)  

clip  = clip[startpos:endpos]
audio = audio[to_samples(startpos):to_samples(endpos)]
where startpos,endpos are frames, but you have them as time

Last edited by _Al_; 13th August 2022 at 20:09.
_Al_ is offline   Reply With Quote
Old 13th August 2022, 20:15   #3  |  Link
MysteryX
Soul Architect
 
MysteryX's Avatar
 
Join Date: Apr 2014
Posts: 2,559
If pos is in seconds, basically you're doing:

Code:
clip = core.lsmas.LibavSMASHSource(source)
audio = vs.core.bas.Source(source, track=-1)

def to_samples(second):
    return math.floor(audio.sample_rate * second)

clip = clip.std.Trim(first = startpos * clip.fps, length = length * clip.fps)
audio = audio.std.AudioTrim(first = to_samples(startpos), length = to_samples(length))
The returned audio is WAY too short.

For a 5-second encode, audio encode says: Output 240000 samples in 1.81 seconds

no wait -- audio is fine 5 seconds, problem seems to be with the audio/video muxing

Last edited by MysteryX; 13th August 2022 at 20:22.
MysteryX is offline   Reply With Quote
Old 13th August 2022, 20:20   #4  |  Link
_Al_
Registered User
 
Join Date: May 2011
Posts: 321
Slicing operates different than trim maybe, if using slicing, that last integer in trim is not included, you perhaps cannot mix slicing and trim
try:
Code:
start_time = 5 #5seconds
length = 10 #seconds

start  = int(clip.fps * start_time)
end    = int(start + length*clip.fps)

clip  = clip[start:end]
audio = audio[to_samples(start):to_samples(end)]
Your funct. is different, rounding errors? How trim function rounds up numbers, meaning float frame to int frame, I'd make sure both clip and audio gets same integer frames for either slicing or trim.

Last edited by _Al_; 13th August 2022 at 20:36.
_Al_ is offline   Reply With Quote
Old 13th August 2022, 21:11   #5  |  Link
MysteryX
Soul Architect
 
MysteryX's Avatar
 
Join Date: Apr 2014
Posts: 2,559
The issue was with the output with ffmpeg

mov file with prores doesn't support PCM audio. I changed it to mkv and it works. Hopefully DaVinci Premiere opens the MKV file fine.

Code:
vspipe -o 1 -c wav "denoise.vpy" - | ffmpeg -i pipe: -c:a pcm_s16le Output.wav
vspipe -o 0 -c y4m "denoise.vpy" - | ffmpeg -i pipe: -i Output.wav -c:v prores -c:a copy "Output.mkv"
rm Output.wav
MysteryX is offline   Reply With Quote
Old 13th August 2022, 22:08   #6  |  Link
_Al_
Registered User
 
Join Date: May 2011
Posts: 321
videoeditors have function to group a video and audio to one if needed, if it comes to it, maybe you do not need to have video and audio in one container,

just remembered, DJATOM posted a function that does trimming for both , video and audio
https://forum.doom9.net/showthread.p...80#post1933080

looking at that DJATOM class, it could be avoided to call data() method at the end if def __call__ () is used instead of def data(), and using instead :
vclip, aclip = Trim((vclip, aclip), 18544, 18582)() + Trim((vclip, aclip), 18687, 18724)()
not tested yet, someone might try, but adding might not work then, not sure ...

Last edited by _Al_; 13th August 2022 at 22:38.
_Al_ is offline   Reply With Quote
Old 14th August 2022, 06:04   #7  |  Link
MysteryX
Soul Architect
 
MysteryX's Avatar
 
Join Date: Apr 2014
Posts: 2,559
Actually DaVinci doesn't like prores in a MKV container... need to muxe them back into separate files
MysteryX is offline   Reply With Quote
Old 15th August 2022, 05:08   #8  |  Link
_Al_
Registered User
 
Join Date: May 2011
Posts: 321
Or how about this, is this too much fuss for just trimming or multiplying pair of video and audio?
PHP Code:
#python code
import vapoursynth as vs
from vapoursynth import core
from dataclasses import dataclass
field
@dataclass
class Pair:
    
vnodevs.VideoNode field(default_factory=lambdacore.std.BlankClip())
    
anodevs.AudioNode field(default_factory=lambdacore.std.BlankAudio())

    
def trim(selfstartend):
        return 
Pairself.vnode[start:end],
                     
self.anode[self.to_samples(start):self.to_samples(end)]
                    )

    
def to_samples(selfframe):
        return 
int((self.anode.sample_rate/self.vnode.fps)*frame)  

    
def __add__(selfother):
        return 
Pair(self.vnode other.vnodeself.anode other.anode)
    
    
def __mul__(selfmultiple):
        return 
Pair(self.vnode*multipleself.anode*multiple)

vnode core.lsmas.LibavSMASHSource(r"video_source.mp4")
anode core.bas.Source(r"video_source.mp4")
#some custom vnode filtering
vnode vnode.std.Levels(min_in=16max_in=235min_out=0max_out=255planes=0)
#to pair video and audio for trimming or multiplying
pair Pair(vnodeanode)
pair pair.trim(201000) + pair.trim(10012000) + pair.trim(2500vnode.num_frames)  #adding
pair pair # or pair + pair, doubling the length
print(pair.vnodepair.anode)
pair.vnode.set_output()
pair.anode.set_output(1)
#or just continue script with vnode fix ups only using vnode = pair.vnode, or just using pair.vnode all the time 
_Al_ is offline   Reply With Quote
Old 23rd February 2023, 21:54   #9  |  Link
_Al_
Registered User
 
Join Date: May 2011
Posts: 321
How about this, to drag audio along video. Trim arguments have the same syntax as vapoursynth' Trim. But also slicing could be used:

Code:
class Clip:
    def __init__(self, video = None, audio=None, attribute_audio_path=None):
        self.video = video
        self.audio = audio
        if self.video is None:
            self.video = core.std.BlankClip()
        if self.audio is None:
            if attribute_audio_path is None:
                raise ValueError('argument attribute_audio_path is needed to get default audio for images (could be a really short video')
            attr_audio = core.bas.Source(attribute_audio_path)
            length = int(attr_audio.sample_rate/self.video.fps*self.video.num_frames)
            self.audio = attr_audio.std.BlankAudio(length=length)

    def trim(self, first=0, last=None, length=None):
        afirst  = self.to_samples(first)    if first  is not None else None
        alast   = self.to_samples(last+1)-1 if last   is not None else None
        alength = self.to_samples(length)   if length is not None else None
        return Clip( self.video.std.Trim(first=first, last=last, length=length),
                     self.audio.std.AudioTrim(first=afirst,last=alast,length=alength)
                    )
    def to_samples(self, frame):
        return int((self.audio.sample_rate/self.video.fps)*frame)

    def __add__(self, other):
        return Clip(self.video + other.video, self.audio + other.audio)

    def __mul__(self, multiple):
        return Clip(self.video*multiple, self.audio*multiple)

    def __getitem__(self, val):
        if isinstance(val, slice):
            if val.step is not None:
                raise ValueError('Using steps while slicing AudioNode together with VideoNode makes no sense')
            start = self.to_samples(val.start) if val.start is not None else None
            stop =  self.to_samples(val.stop)  if val.stop  is not None else None
            return Clip( self.video.__getitem__(val),
                         self.audio.__getitem__(slice(start,stop))
                         )
        elif isinstance(val, int):
            start = self.to_samples(val)
            stop = int(start + self.audio.sample_rate/self.video.fps)
            return Clip( self.video[val],
                         self.audio.__getitem__(slice(start,stop))
                         )        
    def __repr__(self):
        return '{}\n{}\n{}'.format('Clip():\n-------', repr(self.video), repr(self.audio))

    def __str__(self):
        return '{}\n{}\n{}'.format('Clip():\n-------', str(self.video), str(self.audio))
Creates class that carries both vs.VideoNode and vs.AudioNode.
Using the same syntax as for vs.VideoNode on this class object for: trim/slice, add, multiply or print,
the same operation is also done to the audio at the same time
examples:
Code:
from vapoursynth import core
video = core.lsmas.LibavSMASHSource('video.mp4')
audio = core.bas.Source('video.mp4')
clip = Clip(video, audio)
clip = clip[0] + clip[20:1001] + clip[1500:2000] + clip[2500:]
#or same trimming calling trim method:
clip = clip.trim(first=0, length=1) + clip.trim(firt=20, last=1000) + clip.trim(1500, length=500) + clip.trim(2500)
clip = clip*2
clip = clip + clip
clip.video.set_output(0)
clip.audio.set_output(1)
Does anyone know how to change samplerate from integer to float for BlankAudio?

Last edited by _Al_; 23rd February 2023 at 22:04.
_Al_ is offline   Reply With Quote
Old 24th February 2023, 12:07   #10  |  Link
kolak
Registered User
 
Join Date: Nov 2004
Location: Poland
Posts: 2,843
Quote:
Originally Posted by MysteryX View Post
The issue was with the output with ffmpeg

mov file with prores doesn't support PCM audio. I changed it to mkv and it works. Hopefully DaVinci Premiere opens the MKV file fine.

Code:
vspipe -o 1 -c wav "denoise.vpy" - | ffmpeg -i pipe: -c:a pcm_s16le Output.wav
vspipe -o 0 -c y4m "denoise.vpy" - | ffmpeg -i pipe: -i Output.wav -c:v prores -c:a copy "Output.mkv"
rm Output.wav
Since when MOV doesn't support PCM?
It supports it perfectly and video codec has nothing to do with it either.
There must be some other issue. MOV can store audio outside video and this may be some hint. There is some issue with piping probably.

Last edited by kolak; 24th February 2023 at 12:10.
kolak is offline   Reply With Quote
Reply

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +1. The time now is 03:41.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.