How to trim video clips instantly without reencoding
bernd.dev
bernd.dev
After all, it is called a stream for a reason... while there's definitely a lower limit to how small you can cut out a piece and have it still decode, as far as I know, all common audio and video codecs are designed with sync codes and "markers" so that a decoder can easily find a valid data block to start decoding from. Something like a broadcasted signal from a TV channel has no start nor end, so decoders need to be able to just jump in at any point and start decoding.
I re-created (I haven't invented this, obviously) a way to split the video file into keyframe segments and mark down the start byte offsets of the keyframes, and then I could "virtually" split the file for streaming, so that a user wouldn't 1) buffer the whole file, 2) need to have the whole file to share to others (P2P in the browser), 3) need to restart the stream and sharing if the connection broke.
This could've obviously been done with HLS or DASH, but that required remuxing the files and keeping lots of them. I instead remuxed files into TS container, indexed all the files, made JSON manifests, and had a network of reverse proxy "CDN" servers on continents that would pull the files from a few central servers, cache the small virtual chunks, which were created by reading byte offsets from the file and serving it as a "file" with PHP.
In the end, the project collapsed due to non-technical issues, and me loosing interest and doing more legitimate and useful things. I then resold the technology a few times to some people who wanted the similar thing but wouldn't have the issues I had, then I moved on and forgot it all.
It's history, it's made my career in some way, at least from my side, it was innovative for it's time, and made me nerdy-cool in school, both with other kids and the school staff.
-
If someone wants to know a bit more, read this: https://www.theverge.com/2015/10/21/9585984/browser-popcorn-... (It's cringe, I was young and stupid, LOL)
While on the topic of ffmpeg uses, here is a script I posted that speedup videos by a factor of 1.5: https://news.ycombinator.com/item?id=22584131 (use case record an unscripted screencast or demo with lots of pauses and uhms, then speed it up to make it look like you are super well prepared and caffeinated --- hidden bonus: if demoing a software product it will appear to be 33% faster!)
I've been playing around a bunch with FFmpeg these last few days because I thought it was ridiculous I had to manually perform certain tasks in ScreenFlow which appeared entirely programmable.
I have another more interesting post on subtitles / captions, but that is for a more niche audience.
Pretty interesting how H.265/HEVC Hardware encoding differs across platforms and how software encoding produces much smaller files at the same quality.
Consumer hardware encoders are more constrained than software in what they can do, and thus are usually designed to optimise what they are best at: encoding speed and power efficiency.
Btw, for some reason ffmpeg doesn't do well with changing speed of music—the result sounds poor compared to VLC. I found that `sox` gives better quality.
Found this page but don't think that's all the hotkeys available even: https://wiki.videolan.org/QtHotkeys/
Especially at 0.85 speed without pitch lock. YouTube can't do that, so you'll have to use an app, like NewPipe on Android, or download the thing.
As for Soulwax, don't miss their earlier mix of new-beat: https://youtube.com/watch?v=4XUipCxjmmw
Avidemux is a FOSS video editing tool I ran into that implements ffmpeg. Since this workflow requires a human to manually evaluate points in time in a video, a single tool seems like a better choice.
A word of warning: ffmpeg can't always cut where you want. Sometimes cutting in a certain point gives you a few blank (black screen) seconds. I guess it's because codecs work by storing what's different from previous frames.
If someone uses Lazarus (or maybe Delphi) it's as simple as:
s := Format('"C:\Program Files\ffmpeg\bin\ffmpeg.exe" -i "%s" -ss %s -c copy -t %s "%s"', [InputFile, Start, Duration, OutputFile]);
Memo1.Lines.Text := s;
WinExec(PChar(s), SW_SHOWDEFAULT);
With the parameters taken from TEdit controls. The TMemo was used to visualize what I was sending to ffmpeg.
As usual it fails to calculate exact frame timings, which means the cuts may not end up exactly where the GUI is telling you (even if you take care to define the cut start at a keyframe).
https://gist.github.com/iwalton3/c034ec5a942466206fbee859184...
The notable function that does video cuts without a full re-encode is shortenVideo, which cuts a certain number of seconds off the beginning of a video. I've never had any issues with it, but I only used it on h264 mp4 files.
I've Googled and tried this so many times but there are so many filters and knobs I half-understand (at best) that I haven't really managed to find one I actually like in practice, but I feel like it must be possible given that people post videos online that do this extremely well.
I haven't tried either approach.
[1]: https://www.youtube.com/watch?v=nU8zqn091rM
[2]: http://blog.gregzaal.com/2014/05/30/camera-stabilisation-wit...
What Blender won't help you with (I haven't found it at least) is removing the motion blur that happens because of the camera shake. Which is fine, Blender is not a post-production tool, but worth knowing that if you want to stabilize footage, you probably need Blender + insert-favorite-post-production-tool.
function stabilize {
tempfile=".temp$RANDOM$RANDOM.trf"
ffmpeg -nostdin -loglevel error -y -i "$1" -vf vidstabdetect=shakiness=5:show=1:result="$tempfile" -f null -
ffmpeg -nostdin -loglevel error -y -i "$1" -vf vidstabtransform=input="$tempfile",unsharp=5:5:0.8:3:3:0.4 -movflags +faststart "$2"
rm "$tempfile"
}
Usage: stabilize infile outfile.mp4Update: Just tried it. It seems to do some kind of blurring to smooth the vibrations over several frames instead of trying to cancel the shaking by inverse-transforming the frame with respect to the shake. I think I've tried this in my experiments before -- and I guess it's the difference between "de-shake" and "stabilization"? Sadly it doesn't really seem better to my eyes sadly, but thanks for the help anyway.
See here: https://ffmpeg.org/ffmpeg-filters.html#vidstabdetect-1
Maybe your ffmpeg build doesn’t have it? Also try removing the log level parameter.
>which is then used by the vidstabtransform filter.
The first pass is meant to find the rotation, then I assume the next pass cancels it out.
https://www.youtube.com/watch?v=I6E6InIQ76Q&t=9s
They stay stable in the center whereas the rest of the frame is transformed. This necessarily requires introducing black/white crop frames into the image with all kinds of shapes and sizes, but it turns out incredibly smooth and doesn't lose any of the frame. It also requires no noticeable blurring at all from what I can tell. But that doesn't seem to be quite what's happening with these commands though.
I was able to find this comment thread where a user posted some ffmpeg scripts to replicate the behavior. Am on mobile currently so I can't verify they do what you're looking for but here's a snippet.
//PART 1 [Defaults: shakiness=5:accuracy=15:stepsize=6:mincontrast=0.3:show=0] ffmpeg -i shaky-input.mp4 -vf vidstabdetect=shakiness=5:accuracy=15:stepsize=6:mincontrast=0.3:show=2 dummy_crop.mp4
//PART 2 ffmpeg -i shaky-input.mp4 -vf scale=trunc((iw0.90)/2)2:trunc(ow/a/2)*2 scaled_crop.mp4
//PART 3 [-strict -2 ONLY IF OPUS AUDIO] - [Unsharp Default: '5:5:1.0:5:5:0.0'] ffmpeg -i scaled_crop.mp4 -vf vidstabtransform=smoothing=20:input="transforms.trf":interpol=no:zoom=-10:optzoom=2,unsharp=5:5:0.8:3:3:0.4 stabilized_crop-output.mp4
https://www.reddit.com/r/stabbot/comments/9f7ayj/comment/e5x...
I don't think vidstab can do exactly what's being asked for here, I've never seen it rotating the frame completely to keep a rotating pen stabilized, or move the frame inside a larger canvas to keep a moving subject centered. I think you have to use video editing and do that manually.
Perhaps you just need to increase the smoothing parameter. I found the default of 10 way too low, and needed around 50-100 for my very shaky 50 fps home videos.
Not command line though.
https://ffmpeg.org/ffmpeg.html#Main-options
> -ss position (input/output)
> When used as an input option (before -i), seeks in this input file to position. Note that in most formats it is not possible to seek exactly, so ffmpeg will seek to the closest seek point before position. When transcoding and -accurate_seek is enabled (the default), this extra segment between the seek point and position will be decoded and discarded. When doing stream copy or when -noaccurate_seek is used, it will be preserved.
> When used as an output option (before an output url), decodes but discards input until the timestamps reach position.
It is much slower when used an output option, and I don't really know what it does when you do stream copy, but I suspect it leaves the whole segment with some sort of offset instruction. I often get artefacts when I play it back on vlc, so I try to avoid that option (unless I am re-encoding).
I believe this has no effect on whether or not you can cut precisely - if transcoding is not enabled, even if ffmpeg is sticking the frames before the first keyframe in the output file, they're effectively garbage from the point of view of the decoder (which might explain why you see artifacts in some players).
It's possible to reencode a (h264-encoded, at least) video up to the first keyframe; it's discussed in this StackExchange submission: https://video.stackexchange.com/a/23542
Coincidentally, I refined the above approach very recently and posted the result to my own blog: https://csrd.science/blag/2020/trimming-an-h264-video-and-pr...
The gist is to extract and reencode the segment containing the group of pictures to be cut (using the stream segment muxer), then rejoin the subsequent segments and remux the trimmed audio back in afterwards.
Certainly if the duration specified doesn't land you on a key frame it also ends at the closest keyframe.
Would the following work?
# Calculate the exact start time (in s.msec format) via: START = start_frame_number/frames_per_second
ffmpeg -ss $START -i video.mp4 -c copy -map 0 -frames 1400 output.mp4
Screencasts don't need frame precision fortunately. A set up that isn't completely polished also feels more authentic.
It was an instant processing thing but I don't remember for sure if it was the same command.
For splitting an audiobook into pieces, so that you can use the seek bar sanely, `mp3splt` can be used in one run pretty much at the disk's speed. Its format language for metadata is atrocious, but thankfully putting the result into a script frees me from revisiting the horror.
Here's the command I use to cut into 10-minute pieces without a 1-minute piece hanging at the end, and to name and title the pieces sequentially—so you can be spared the ordeal:
mp3splt -t '10.00>2.00' -o '@f @n2' -d . -g 'r%[@o,@N=1,@t=#t @N]' "$1"
—where $1 is the source file, and `.` is the current directory as the destination.
IIRC it also comes with oggsplt and flacsplt—but no such luck for aac or ac3.
ffmpeg -ss $START -i $INFILE -c copy -map 0 -to $END $OUTFILE
This is functionally the same as ffmpeg -ss $START -i $INFILE -c copy -map 0 -t $END $OUTFILE
FFmpeg normalizes input timestamps unless told otherwise via -copyts. So, in the first command, output timestamps start from 0, effectively making -to a duration limiter.Both -ss and -to should be on the same side of the input for (close to) expected result.
VirtualDub and Avidemux are (simple) video editors that do it exactly the same way.
Here’s a simple command-line tool: http://ben.com/jpeg/
This one has a UI, but no screenshotS of it (scroll down to jpegcrop), and it also mentions lossless rotation which I haven’t investigated: https://jpegclub.org/
This page explains a bit more about lossless operations and mentions that Irfanview has them—it’s a great image viewer for that I use, and I didn’t even know: https://www.impulseadventure.com/photo/lossless-rotation.htm...
I have been looking for lossless (reencode-less) trimming of videos since the end of 90s and always just found huge video editing tools that never had these features. And then ypu were stuck with some CLI tools where you need to count the number of frames or milliseconds or something like that. Like if a WYSIWYG tool isn‘t what most people would want to use.
How does the native iOS photo editing tool handle video trimming? And photo cropping? iMovie? And what about google android tools? Or popular Windows tools?
I used to crop my photos with XnView, which supports lossless cropping. And I‘m always puzzled this hasn‘t really take off in other popular tools.
Lossless crop of photos and lossless trim of videos should always be included as a feature.
Reencoding sucks.
On iOS the trimming is done losslessly, when you trim a clip it basically does the same as what `ffmpeg` is doing here. It seeks to the new start time and copies all the GOPs (group of pictures) to the new end point. The camera records video with really short GOPs so the trimming can be pretty accurate. Only if you apply filters or crop the dimensions of the video will the trimmed clip be reencoded. Any iOS software using AVKit can do the same lossless trims, I imagine most editors on iOS do.
When doing rotation I know the Photos app just changes the JPEG rotation flag in the EXIF data. If you send the raw photo to something that ignores or doesn't understand EXIF rotation you'll see just the sensor's default orientation. I believe HEIF works the same way (the container has a rotation atom). When exporting an image (reencoding for sharing or after editing) it will bake in the rotation to the image data, actually performing the rotation to the image.
http://www.digital-digest.com/articles/virtualdubmod_cutavi_...
Admittedly it's aging a bit and doesn't support a lot of newer formats, but I still find it useful. As much as I enjoy command line, having the gui is nice to mark in&out points and do the trimming all in one spot. You'd still have to open a video player to figure out where to start & end.
[1] https://github.com/Kagami/ffmpeg.js/ [2] https://zvakanaka.github.io/vidslicer/
I recently had to cut (for reasons) an mp4 video somebody sent me over Whatsapp.
After fighting with ffmpeg for a day - they hey word here is "keys" - because there were issues with the video: Sound would start at point but video didn't, or the first part before the first key in it of the video was re encoded and the quality was crap I finally resorted to using Handbrake, that did the job I needed.
Just get any short video somebody sent you and try do use this script, and you'll see what I'm talking about.
The difference is explained here: http://www.markbuckler.com/post/cutting-ffmpeg/
p.s. I'm more than sure that there's ffmpeg port to windows, but I've just used it via Ubuntu on WSL (1.0) and it worked perfectly on a 3.72GB file of 8 something minutes length:
time=00:00:38.47 bitrate=67220.6kbits/s speed=91.8x
ffmpeg -i video.mp4 -itsoffset 0.25 -i audio.ogg -c copy -y av.mkv
Can you point me to the original?
If you have suggestions for a better meme I can change it :)
Snippet: https://giphy.com/gifs/whoa-hd-tim-and-eric-xT0xeJpnrWC4XWbl...
Full video: https://youtu.be/FYJ1dbyDcrI
I was also happy that this FFmpeg approach properly maintained all my subtitle streams. That's something I was working with a few days ago if you look at the other post on my blog.
npm install ffmpeg-static@latest
It works on windows, mac, and linux. Gets installed locally (don't have to muck up my system). I do have to look up the path but I don't mind node_modules/ffmpeg-static/bin/<os>/x64/ffmpeg $ sudo apt-get install ffmpeg
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following additional packages will be installed:
i965-va-driver intel-media-va-driver libaacs0 libaom0 libass9 libavcodec58 libavdevice58 libavfilter7 libavformat58
libavresample4 libavutil56 libbdplus0 libbluray2 libbs2b0 libchromaprint1 libcodec2-0.8.1 libcrystalhd3 libdc1394-22
libflite1 libgme0 libgsm1 libigdgmm5 liblilv-0-0 libmysofa0 libnorm1 libopenal-data libopenal1 libopenjp2-7
libopenmpt0 libpgm-5.2-0 libpostproc55 librubberband2 libsdl2-2.0-0 libserd-0-0 libshine3 libsnappy1v5 libsndio7.0
libsord-0-0 libsratom-0-0 libssh-gcrypt-4 libswresample3 libswscale5 libva-drm2 libva-x11-2 libva2 libvdpau1
libvidstab1.1 libx264-155 libx265-165 libxvidcore4 libzmq5 libzvbi-common libzvbi0 mesa-va-drivers
mesa-vdpau-drivers va-driver-all vdpau-driver-all
Suggested packages:
ffmpeg-doc i965-va-driver-shaders libbluray-bdj firmware-crystalhd libportaudio2 serdi sndiod sordi libvdpau-va-gl1
nvidia-vdpau-driver nvidia-legacy-340xx-vdpau-driver nvidia-legacy-304xx-vdpau-driver
The following NEW packages will be installed:
ffmpeg i965-va-driver intel-media-va-driver libaacs0 libaom0 libass9 libavcodec58 libavdevice58 libavfilter7
libavformat58 libavresample4 libavutil56 libbdplus0 libbluray2 libbs2b0 libchromaprint1 libcodec2-0.8.1
libcrystalhd3 libdc1394-22 libflite1 libgme0 libgsm1 libigdgmm5 liblilv-0-0 libmysofa0 libnorm1 libopenal-data
libopenal1 libopenjp2-7 libopenmpt0 libpgm-5.2-0 libpostproc55 librubberband2 libsdl2-2.0-0 libserd-0-0 libshine3
libsnappy1v5 libsndio7.0 libsord-0-0 libsratom-0-0 libssh-gcrypt-4 libswresample3 libswscale5 libva-drm2 libva-x11-2
libva2 libvdpau1 libvidstab1.1 libx264-155 libx265-165 libxvidcore4 libzmq5 libzvbi-common libzvbi0 mesa-va-drivers
mesa-vdpau-drivers va-driver-all vdpau-driver-all
0 upgraded, 58 newly installed, 0 to remove and 1 not upgraded.
Need to get 34.7 MB of archives.
After this operation, 145 MB of additional disk space will be used.
Do you want to continue? [Y/n] n
vs $ npm install ffmpeg-static
> ffmpeg-static@4.1.0 install /home/gregg/temp/node_modules/ffmpeg-static
> node install.js
Downloading ffmpeg [||||||||||||||||||||] 100% 0.0s
+ ffmpeg-static@4.1.0
added 19 packages from 52 contributors and audited 21 packages in 14.318s
found 0 vulnerabilities
No admin need, no system libs to install, it just works.