Video codec, real-time audio and video, webrtc, real-time interaction, use ffmpeg to convert mp4 to m3u8.

1. MP4 to M3U8

M3U8 is the Unicode version of M3U, encoded in UTF-8. “M3U” and “M3U8” files are both the basis for the HTTP Live Streaming (HLS) protocol format used by Apple, which can be played on devices such as iPhones and Macbooks.

Simply put, m3u8 is a video format that divides a video into many small parts to facilitate the loading of the video.

1. Simple operation, but low efficiency

ffmpeg -i input.mp4 -c:v libx264 -c:a aac -strict -2 -f hls -hls_list_size 2 -hls_time 15 output.m3u8

The resulting effect is:

Generate a ts file from the input.mp4 video file every 15 seconds, and finally generate an m3u8 file. The m3u8 file is the index file of ts.

We can directly use VLC media player and other playback software to directly open m3u8 files, just like playing mp4.

The default length of each clip is 2 seconds. By default, the m3u8 file only saves the information of the latest 5 clips. As a result, only the last small part can be played during the final playback (pay special attention during live broadcast). -hls_time n Set the length of each slice, the default value is 2, the unit is seconds. -hls_list_size n sets the maximum number of entries saved in the playlist. If set to 0, all film information will be saved. The default value is 5. -hls_wrap n Set how many slices to start covering after. If set to 0, it will not be covered. The default value is 0. This option avoids storing too many slices on disk and limits the maximum number of slices written to disk. -hls_start_number n sets the value of sequence number in the playlist to number, and the default value is 0. NOTE: The playlist sequence number must be unique for each segment, and it must not be confused with the slice filename (filenames may be reused when using the wrap option).

2. Efficiency optimized version to improve efficiency

TS file is a media extension that is a packaging format captured by Japanese high-definition cameras. MPEG2-TS (Transport Stream; also known as TS, TP, MPEG-TS or M2T) is a communication protocol for audio, image and data. It was first used in the real-time transmission of DVD programs. The characteristic of the MPEG2-TS format is that it requires that any segment of the video stream can be decoded independently.

# 1. Overall video transcoding ts

ffmpeg -y -i music.mp4 -vcodec copy -acodec copy -vbsf h264_mp4toannexb out\music.ts

2. ts file slicing

ffmpeg -i music.ts -c copy -map 0 -f segment -segment_list out\music.m3u8 -segment_time 10 out\15s_=.ts

3. The problem of inaccurate hls_time slicing time

To play the ts slice of m3u8, you must download a ts slice completely before it can be played. The shorter the time interval of setting hls_time is, the better (according to the actual situation). In the actual process, set the slice time interval to 2 seconds and call the following command:

ffmpeg -i test.mp4 -c:v libx264 -c:a aac -strict -2 -f hls -hls_time 2 index.m3u8

But it does not perform slicing according to the parameter input.

reason:

The cutting of ts files is also related to the GOP size of the original file video (that is, the time interval between two I frames), because the first frame of any ts slice must be an I frame, otherwise it cannot be played as quickly as possible, and The first frame is not an I frame and has no meaning to the player, so it is directly thrown away by the player. Any video stream must obtain the first I frame before it can successfully decode the picture. Although 1 second is specified to cut a ts file, in fact, since the original video stream may not have an I frame for several seconds, you must wait until the next I frame before slicing starts again.

solve:

Now that we know that one ts slice will be generated in one second, we must force one key frame to be generated in one second during the slice generation process.

Set the key frame interval. The parameters for setting the interval to 2 seconds are as follows: -force_key_frames “expr:gte(t,n_forced*2)”

The complete instruction is as follows:

ffmpeg -i test.mp4 -force_key_frames "expr:gte(t,n_forced*2)" -strict -2 -c:a aac -c:v libx264 -hls_time 2 -f hls index.m3u8</ pre>
<p>4. m3u8 format analysis</p>
<p>The complete m3u8 file has three parts:</p>
<p>index.m3u8, saves the basic information of the video and the sequence of segmented files; key, if the video is encrypted, saves the key; data file, the others are the data files of the video.</p>
<p>Specific content analysis:</p>
<p>#EXTM3U, is the beginning of the file #EXT-X-VERSION, identifies the protocol version number of HLS; #EXT-X-TARGETDURATION, indicates the maximum duration of each video segment (in seconds); #EXT-X-MEDIA-SEQUENCE, Represents the serial number of the first URL fragment file of the playlist; #EXT-X-PLAYLIST-TYPE, indicates the streaming media type; #EXT-X-KEY, encryption method, here the encryption method is AES-128, and the IV is specified at the same time Required when decrypting; #EXTINF, indicating the length of the media segment specified by the subsequent URL (in seconds).</p>
<p>2. Play the demo</p>
<p>The working principle of HLS is to divide the entire stream into small HTTP-based files for download, and only download a few at a time.</p>
<p>While a media stream is playing, the client can choose to download the same resource at different rates from many different alternative sources, allowing the streaming session to accommodate different data rates.</p>
<p>When starting a streaming session, the client downloads an extended M3U (m3u8) playlist file containing metadata used to find available media streams.</p>
<p>HLS only requests basic HTTP messages. Unlike Real-Time Transport Protocol (RTP), HLS can pass through any firewall or proxy server that allows HTTP data to pass through.</p>
<p>It's also easy to use a content delivery network to stream media.</p>
<p>3. Merge m3u8(ts) into MP4</p>
<p>remote file</p>
<pre>ffmpeg -i “https://xushanxiang.com/demo/ffmpeg/hls265/output.m3u8” -vcodec copy -acodec copy -absf aac_adtstoasc output.mp4

local files

1. Open cmd

2. Enter the command to merge according to the actual path of the file.

Merge into ts files copy /b F:\f\*.ts E:\f\\
ew.ts

Merge into MP4 files copy /b F:\f\*.ts E:\f\\
ew.MP4

The ffmpeg command is as follows:

Direct transfer: ffmpeg -i new.ts -c copy -map 0:v -map 0:a output.mp4

Specify the audio stream (usually use this): ffmpeg -i new.ts -c copy -map 0:v -map 0:a -bsf:a aac_adtstoasc output.mp4

Re-encode video: ffmpeg -y -i new.ts -c:v libx264 -c:a copy -bsf:a aac_adtstoasc output.mp4

php implementation code

$url = 'https://******.m3u8?Expires=1585381145 & amp;OSSAccessKeyId=****** & amp;Signature=******';

$ts_content = file_get_contents($url);

$ts_content = explode(',', $ts_content);

$ts_file = array();

foreach ($ts_content as $key => $value) {

if($key == 0) continue;

$value = trim($value);

$ts_file[] = substr($value, 0, strpos($value, '.ts') + 3);

}

$url_prefix = substr($url, 0, strpos($url, '.m3u8'));

$url_prefix = substr($url, 0, strrpos($url, '/') + 1);

$file_content = '';

foreach ($ts_file as $key => $value) {

$file_content .= file_get_contents($url_prefix . $value);

}

file_put_contents('tmp_out.ts', $file_content);

// FFMPEG_PATH is the bin path to decompress ffmpeg yourself, for example, mine is F:/ffmpeg/bin/

exec(FFMPEG_PATH . "ffmpeg -i tmp_out.ts tmp_out.mp4");

Python implementation code

Directory Structure

./

|– m3u8.py

|– result

|– File 1

|– key

|– index.m3u8

|– data…

|– File 2

|– …

import os

importsys

import time

from Crypto.Cipher import AES

def fileList(findex):

rpath = os.path.dirname(os.path.realpath(findex))

name = rpath.split("\")[-1]

fi = open(findex, 'r')

flag=False

IV = None

tl = []

for line in fi.readlines():

if line.startswith("#EXT-X-KEY"):

# Extract IV if it exists;

if line.split(",")[-1].startswith("IV="):

IV = line.split(",")[-1][5:]

IV = bytes.fromhex(IV)

if line.startswith("#EXTINF"):

flag = not flag

continue

if flag:

tmp = line.strip().split("/")[-1]

tmp = os.path.join(rpath, tmp)

tl.append(tmp)

flag = not flag

fi.close()

fk = open(os.path.join(rpath, "key"), 'rb')

key = fk.read()

fk.close()

return name, tl, key, IV

def aes_decode(data, key, IV):

# If no IV value is specified, the key value is used directly

if not IV:

IV = key

cryptor = AES.new(key, AES.MODE_CBC, IV)

plain_text = cryptor.decrypt(data)

return plain_text

def main():

fp = os.listdir()

used = [s[:-4] for s in os.listdir("./result/")]

for ind in fp:

if not ind.isdigit():

continue

ifind in used:

continue

try:

name, fl, key, IV = fileList(os.path.join(ind, "index.m3u8"))

except:

print("-"*30)

print("[-] Errot! file: ", ind)

print("-"*30)

continue

print("[*] Begin process file: ", name)

start = time.time()

f = open(os.path.join("./result/", name + ".mp4"), 'ab')

for i in fl:

with open(i, 'rb') as inf:

data = inf.read()

f.write(aes_decode(data, key, IV))

f.close()

print("[ + ] Sucessfully! Cost time: ", time.time()-start)

main()

The knowledge points of the article match the official knowledge files, and you can further learn related knowledge. Network Skill TreeHomepageOverview 41743 people are learning the system