Extract Sub-clip

Shotcut can not “pass through” or copy codecs without re-encoding. The closest thing available to that is Properties > menu > Extract sub-clip, which uses the in and out points of a trimmed clip.

Extract sub-clip will find the key frame closest to the in/out points and copy the codecs into a new container without re-encoding. Any filters applied to the clip will not be applied to the sub-clip because that would require re-encoding.

This feature has some limitations and may not always provide the expected result:

  • The extraction will round to the nearest codec keyframe - which could be more than a second a way from the selected in/out points
  • The extraction tries to pack the media into the same container format as the original. But it may not always be able to get the packing or timing to match the original
2 Likes

Useful - I never knew trhat. Thanks for sharing.

That’s why extracting a sub-clip is so fast. Good to know.

In this discussion though Dan mentioned this: “This is not an often used function for editing, and it should not be as it is not very accurate or reliable depending on the format and how it was coded.

Is it possible to elaborate here on how extracting a sub-clip is not reliable and what are the eventual consequences?

I suspect it is because it has to have an I-frame as the first frame of the sub-clip. If the GOP is very large, the I-frame could be seconds earlier/later than than the time at which the user wants his sub-clip to start. e.g. a GOP of 120 in a 30fps video could be 2 seconds earlier or later than the user wants.

1 Like

This makes sense @Elusien. I see why this could be a problem. Especially if you extract very short clips.
Thanks.

Although I just tried to export 2 sub-clips from a video with GOP=125 and both exported exactly the correct sub-clip. i.e. the from-frame, to-frame matched exactly the exported start-frame and end-frame. So I’m not sure what is happening.

I added a couple notes to the first post. Maybe we can add to the list as we discover things.

Maybe you are very lucky at selecting frames that are coded in a keyframe!

I don’t think so. The GOP was 125, the first frame was frame 35 (not an I-frame) and that was the first frame of the exported sub-clip. I’ll do a couple more experiments though to check after dinner. Just settled down with a glass of red wine to celebrating winning the golf competition today, having played 8 better than my handicap!

Congratulations!
Please tell us you didn’t modified your golf balls with one of your clever scripts. That would be cheating :rofl:

I’m just wondering: could the extract sub-clip call be used as a special export preset(/mode/option?) on the entire timeline to ignore all filters, just keep the in/out for every clip and merge them together for an ultra fast/original-quality export mode?

Maybe someone could program a mode like that. But it would have to completely bypass the underlying framework because the framework is designed around uncompressed data. And if someone did implement this, the circumstances would have to be perfect to get good results: the codec parameters for all clips would have to be an exact match and the clips would need to use a closed GOP.

About once a year someone comes around suggesting that we add the “-codec copy” switch for FFMpeg because they incorrectly assume that Shotcut is a UI wrapper for FFMpeg. Shotcut is built on the MLT framework which does not have a concept of compressed data. The MLT framework uses the FFMpeg library functions to convert between compressed and uncompressed data.

1 Like

while avidemux supports codec copy for mutliple cuts in one video but lacking a fancy GUI like shotcut, I wrote a ruby script to convert a shotcut mlt file to avidemux project python script.
Please note that this script only supports simplest shotcut project containing only one video file and you performed only multiple cut operations on it.

#!/usr/bin/env ruby
require 'rexml/document'
require 'time'
include REXML  # to avoid constantly prefixing objects with REXML:: prefix

# 1. use shotcut to cut a video, because it has a better GUI with a audio wave form panel
# 2. use this script to convert shotcut project file(mlt) to a avidemux project python script
# 3. use `avidemux3_cli --run generated.py` or avidemux GUI to run that script, because avidemux support codec copy to avoid transcoding
abort "Usage: mlt2avidemux shotcut.mlt > generated.py" if ARGV.empty?

# NOTE: only tested for <mlt LC_NUMERIC="C" version="7.17.0" title="Shotcut version 23.05.14" producer="main_bin">
doc = Document.new(File.open(ARGV[0]))

playlist = doc.elements["mlt/playlist[@id='playlist0']"]
entries = playlist.elements.to_a("entry")

segments = []
video_path = nil
timepoints = entries.map do |entry|
  producer = entry.attributes["producer"]
  resource = doc.elements["mlt/chain[@id='#{producer}']/property[@name='resource']"].text
  if video_path == nil
    video_path = resource
  elsif video_path != resource
    $stderr.puts "#WARNING: ignore playlist entry resource #{resource}"
    next
  end
  t_in = Time.parse("1970-01-01T#{entry.attributes["in"]}Z")
  start_microsec = (t_in.to_f * 1000 * 1000).to_i
  t_out = Time.parse("1970-01-01T#{entry.attributes["out"]}Z")
  duration_microsec = ((t_out - t_in) * 1000 * 1000).to_i
  segments << "adm.addSegment(0, #{start_microsec}, #{duration_microsec})"
end

puts <<-EOF
adm = Avidemux()
adm.loadVideo("#{video_path}")
adm.clearSegments()
#{segments.join("\n")}
adm.markerA = 0
adm.videoCodec("copy")
adm.audioCodec(0, "copy")
adm.setContainer("MKV")
adm.save("#{video_path}.out.mkv")
EOF