Skip to content

Instantly share code, notes, and snippets.

@CAD97
Last active June 1, 2020 16:50
Show Gist options
  • Save CAD97/300fac4563e11b9d76d3e46c9bcc2a51 to your computer and use it in GitHub Desktop.
Save CAD97/300fac4563e11b9d76d3e46c9bcc2a51 to your computer and use it in GitHub Desktop.
Python script to use ffmpeg to split mp4 with a video stream and three audio streams into component parts

Why

I use OBS to record and stream, and it allows me to record multiple audio streams to the output container (.mp4). The advantage to doing this is that in post-production (for the recordings) I can then adjust the relative volumes of the differing streams if the balance wasn't perfect in recording. Thus, I'm recording a mixed track 1, my voice only to track 2, and my computer sound out to track 3. (Streaming only takes one track.)

Unfortunately, my editing software (Adobe Premiere Elements 12) doesn't handle multiple audio streams on a .mp4 container. Thus, before I can benefit from having the multiple streams, I need to seperate them out of their container.

The same goes for using Audacity; if I want to mix the separate tracks together using audio editing software, I need to detatch it from the video first.

Thankfully, ffmpeg, which I already had installed, can accomplish this task very easily. It was just a matter of looking up the exact command to split the streams from the input file to seperate output files and then making a script to make the process easier on myself.

import subprocess
import sys, os
def main(file):
name, ext, *r = file.split('.')
if len(r):
raise SyntaxError
command = ['ffmpeg','-i',file,
'-map','0:0','-c','copy',name+' s0.mp4',
'-map','0:1','-c','copy',name+' s1.aac',
'-map','0:2','-c','copy',name+' s2.aac',
'-map','0:3','-c','copy',name+' s3.aac']
print(*command)
subprocess.run(command,stdout=subprocess.PIPE,stdin=subprocess.PIPE)
if __name__ == '__main__':
if len(sys.argv) == 2:
main(sys.argv[1])
else:
print('Usage: %s file' % os.path.relpath(__file__))
import subprocess
import re
import sys, os
def ArgumentError(Exception):
pass
def main(*files):
pattern = re.compile(r'Stream #(0:\d)\(.*?\): (?:Video|Audio): (h264|aac) ', flags=re.M)
for file in files:
print('splitting',file)
name, ext, *r = file.split('.')
if len(r):
raise ArgumentError
fftype = subprocess.run(['ffmpeg','-i',file],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE).stderr.decode()
matches = pattern.findall(fftype)
for n,encoding in enumerate(matches):
print(' >stream',n,encoding)
streamext = ext if encoding[1] == 'h264' else encoding[1]
cmd = ['ffmpeg','-i',file,'-map',encoding[0],'-c','copy',name+' s'+str(n)+'.'+streamext]
subprocess.run(cmd,stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
stdin =subprocess.PIPE)
if __name__ == '__main__':
try:
main(*sys.argv[1:])
except ValueError:
print('Usage: %s file...' % os.path.relpath(__file__))
except:
print('Something went wrong!')
raise
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment