Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to join two video files using Python?

Here I tried to cut first and second 30sec long video file from "path/connect.webm" to the strings out and out1. It works. But what I need to do is to concatenate these two strings and write that to a file "path/final.webm". So that I get a 60sec long video file "final.webm" at the end. But now i get first 30sec long video only as the output. Please help me. Thanks a lot in advance.

Code in python:

import subprocess,os

fname = "/home/xincoz/test/final.webm"

fp = open(fname,'wb')

ffmpeg_command = ["ffmpeg", "-i", "/home/xincoz/test/connect.webm", "-acodec", "copy",   "-ss", "00:00:00", "-t", "00:00:30","-f", "webm", "pipe:1"]

p = subprocess.Popen(ffmpeg_command,stdout=subprocess.PIPE)

out, err = p.communicate()

ffmpeg_command1 = ["ffmpeg", "-i", "/home/xincoz/test/connect.webm", "-acodec", "copy",   "-ss", "00:00:31", "-t", "00:00:30","-f", "webm", "pipe:1"]

p1 = subprocess.Popen(ffmpeg_command1,stdout=subprocess.PIPE)

out1, err1 = p1.communicate()

string = out + out1

print len(out)

print len(out1)

print len(string)

fp.write(string)

fp.close()

Please help me.

like image 874
rash Avatar asked Jun 26 '13 04:06

rash


2 Answers

This seems like one of the two questions any reasonable person would ask when first trying to deal with video, programmatically. 'Why can't I just cut and paste the parts I want?' No one answers because the people who really can explain, are sick of the question, and people like me who have figured it out somewhat on their own, don't want to look stupid. But I don't mind - so here's the practical answer.

To clip and join complex container formats, it's always more complicated than you think, and requires, at the very least, a solution-per-container.

If you read the ffmpeg faq, in theory you can concatenate videos by reformatting them as mpg-v1 (maybe mpg-v2 also works) and then doing more or less what you're doing.

cat first_part.mpg second_part.mpg > joined_movie.mpg

In practice, the joined_movie.mpg, may or may not run smoothly. Even in this very simple format, there's some data upfront, apparently, saying "this file is a minute long" or something like that. So you may open it and discover it's only 30 seconds, but find that it plays for a minute (or not, depending on the player). It can be easily righted (and I assume losslessly, or it wouldn't be recommended in the ffmpeg faq).

But you probably don't want to work with mpg-v1, ultimately. Webm may be a reasonable choice. From what I gather, webm container is derived from MKV. For audio, it uses vorbis and for video it uses vp8. One layman to another: vp8 ~ H264 (I apologize to anyone from doom9 forum who reads this and has a heart attack). Anyway, for us laypeople, the important point is: this means it's not only not simple, but it's actually super complicated-- even just understanding all the encoder parameters is a life's work.

I know mp4box can do something pretty close to what you want with h264 video inside an mp4 container. If you mainly wish to be able to programmatically cut and join video, you could certainly just adopt mp4/h264 instead, but you may be pro-freedom and whatnot, and wish to use webm for ideological or monetary reasons. If you find a solution within webm, I'll be curious. Perhaps mkvtool would work, given its proximity to mkv container?

I'm guessing your files are prepped for streaming, given you're talking about web video. So it may seem like you really really should be able to just add them together. But even with everything interleaved by chunk, it has to be quite a bit more complex than just adding them, or even adding them then adjusting the header/metadata for total playing time. I'm inferring the complexity because it seems like there aren't many tools that will work and even mp4box couldn't always do this reliably/accurately.

If you do go with mp4, you can tell mp4box to join files with:

mp4box -cat file1 -cat file2 -new joined

Perhaps a free-software patriot will post how to cut and join webm files from the command line without reencoding too.

Good luck with your project.

like image 102
Profane Avatar answered Oct 04 '22 06:10

Profane


This code works for me. Thanks all for your great help. Thanks a lot.

import subprocess
ffmpeg_command1 = ["ffmpeg", "-i", "/home/xincoz/test/connect.webm", "-acodec", "copy", "-ss", "00:00:00", "-t", "00:00:30", "/home/xincoz/test/output1.webm"]
ffmpeg_command2 = ["ffmpeg", "-i", "/home/xincoz/test/connect.webm", "-acodec", "copy", "-ss", "00:00:30", "-t", "00:00:30", "/home/xincoz/test/output2.webm"]
ffmpeg_command3 = ["mencoder", "-forceidx", "-ovc", "copy", "-oac", "pcm", "-o", "/home/xincoz/test/output.webm", "/home/xincoz/test/output1.webm", "/home/xincoz/test/output2.webm"]


subprocess.call(ffmpeg_command1)
subprocess.call(ffmpeg_command2)
subprocess.Popen(ffmpeg_command3)
like image 34
rash Avatar answered Oct 04 '22 07:10

rash