SoFunction
Updated on 2025-03-01

Python implements FLV video stitching function

Article summary

This article briefly explains the format of the FLV file. Taking this as the starting point, Python is used to realize the splicing of FLV videos.

1.FLV file format

There are many articles on the Internet about the analysis of FLV file format. Here I will briefly introduce the parts that need to be understood so that readers can better understand the functions of each piece of code.

FLV files are spliced ​​in sequence by splicing the header and the body of the file. Read content in binary when reviewing FLV content.

Header: The file header indicates that the file's encapsulation format is FLV, and the storage object is audio, video, or both.
The following is the header of the FLV file, with a total of 9 bytes:

b'FLV\x01\x05\x00\x00\x00\t'
The first 3 bytes (FLV) means this is an FLV file
The 4th byte (\x01) is the version number, fixed to 1
The 5th byte (\x05) indicates that the object is stored and needs to be converted into binary (00000101) to view. The 1 on the left and right indicates that the file contains audio and video respectively.
The last 4 bytes (\x00\x00\x00\t) represent the length of the file header, and its value is fixed to 9

Body: The file body consists of several tags. Except for the first one, each tag consists of the head (11 bytes), the main body (indefinitely length), and the tail (4 bytes). The first tag has only the tail.

Tags are divided into three categories: scripts, audio (audio) and video (video). Usually the second tag is script type, and there is only one, and the subsequent ones are audio and video types.

The following is the part of the script tag, which is introduced as an example:

Header: b'\x12\x00\tb\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
The 1st byte (\x12) represents the Tag type, the corresponding value of the script type is 18, the audio is 8, and the video is 9.
The 2nd-4th byte (\x00\tb) represents the length of the Tag body, here is 2402
The 5-7th byte (\x00\x00\x00) is a timestamp, and the script type timestamp is usually 0
The 8th byte (\x00) is an extension of the timestamp. When the current 3 bytes are not enough, this byte will be used as the big endian.
The last 3 bytes (\x00\x00\x00) are Stream ids, fixed to 0

Subject: The main body of the script tag contains basic information of FLV video, such as duration, size, resolution, etc., which is relatively complicated and will not be introduced here.

Tail: b'\x00\x00\tm'

Fixed 4 bytes, indicating the length of the Tag head plus the body, that is, 11 + 2402 = 2413

2. FLV video stitching

Synthesize multiple FLV videos into one video that can be played normally, which is enough to meet most needs. Therefore, during the subsequent splicing process, FLV will not be adjusted in detail, and the basic requirements can be met.

Set up the reader

Readers make it easy for us to read file content.

class Reader():
  def __init__(self, content): # content (bytes): Binary content of FLV file     = content
     = 0
     = False # Determine whether the entire content has been read     = len()
    
  def read(self, n=1):
    # Set if statement to prevent over-reading of content    if  > ( + n):
      out = [: + n]
       += n
    else:
      out = [:]
       = True
    return out

Write Header and Tag to the new FLV file

Here it is assumed that the basic information of the video to be spliced ​​is similar, that is, they all contain audio and video, and the resolution, code rate, etc. are the same or similar.

In order to generate a FLV video that can be played normally, header and tags are essential. We can select the file header of the first FLV and write it to the new FLV, and then write the tags with modified timestamps to it in turn to achieve the purpose of splicing.

def add_flv(flv, target, videoTimeStamp, audioTimeStamp): # Modify and add Tag functions  with open(flv, 'rb') as f:
    content = ()
  reader = Reader(content)
  header = (13)
  with open(target, 'ab') as f:
    while not : # Read until it is finished, at this time = True      dataType = (1)
      dataSize = (3)
      timeStamp = int.from_bytes((3), 'big') # Convert 3 bytes to integer      headerRemained = (4)
      if dataType == b'\t': # video        timeStamp += videoTimeStamp
        videoTS = timeStamp
      if dataType == b'\x08': # Audio        timeStamp += audioTimeStamp
        audioTS = timeStamp
      timeStamp = timeStamp.to_bytes(3, 'big') # Convert integers to 3 bytes      tagHeader = dataType + dataSize + timeStamp + headerRemained
      tagData_andSize = (int.from_bytes(dataSize, 'big') + 4)
      (tagHeader)
      (tagData_andSize)
  return videoTS, audioTS
def merge_flv(flvs, target): # Main function  videoTS = 0
  audioTS = 0
  for i, flv in enumerate(flvs):
    with open(flv, 'rb') as f:
      content = ()
    reader = Reader(content)
    
    header = (13) # flvHeader + tagSize0
    if i == 0: # Write the file header of the 1st FLV video      with open(target, 'wb') as f:
        (header)
        
    videoTS, audioTS = add_flv(flv, target, videoTS, audioTS)

Splicing

import time
since = ()
flvs = ['', '', '', ''] # Video size: 45MB, 20MB, 59MB, 54MBtarget = ''
merge_flv(flvs, target)
end = ()
print('Merging flvs takes {:.2f} s'.format(end - since))
# Merging flvs takes 0.88 s

It can be seen that it takes 0.88 seconds to splice 4 178MB videos in total.

Summarize

The FLV file format is relatively concise and the data requirements are relatively loose. Even if the parameters in Scripts are not adjusted, the spliced ​​video can still be played normally.

However, there are many invisible problems with spliced ​​videos, such as the sound and picture may be out of sync (about 0.5 seconds) at the end of the video, and the inability to conveniently separate the complete video and audio.

The above is the Python implementation of FLV video stitching function introduced by the editor. I hope it will be helpful to everyone. If you have any questions, please leave me a message and the editor will reply to everyone in time. Thank you very much for your support for my website!
If you think this article is helpful to you, please reprint it. Please indicate the source, thank you!