欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

使用Python實(shí)現(xiàn)視頻拼接效果

 更新時間:2025年02月07日 16:10:56   作者:AI算法網(wǎng)奇  
這篇文章主要為大家詳細(xì)介紹了使用Python實(shí)現(xiàn)視頻拼接效果的兩種方法,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下

方法一:

視頻較長,分辨率較大,這個效果很好,不耗用內(nèi)存 ffmpeg

 import subprocess
import glob
import os
from natsort import natsorted
base_dir = r'C:\Users\Administrator\Videos\shuiyin\result'
output_file = r'output_shuiyin.mp4'
video_paths = glob.glob(base_dir + '/*.mp4')
video_paths = natsorted(video_paths)
with open('file_list.txt', 'w') as f:
    for file in video_paths:
        f.write(f"file '{file}'\n")
ffmpeg_command = [
    'ffmpeg',
    '-f', 'concat',           # 指定拼接模式
    '-safe', '0',             # 允許絕對路徑
    '-i', 'file_list.txt',    # 輸入的文件列表
    '-c:v', 'libx264',        # 使用 libx264 編碼器
    '-c:a', 'aac',            # 使用 aac 編碼音頻
    '-strict', 'experimental',# 使用實(shí)驗(yàn)性編碼
    output_file               # 輸出文件路徑
]
subprocess.run(ffmpeg_command, check=True)
 
print(f"視頻拼接完成,輸出文件:{output_file}")

方法二:

利用imageio,適合視頻較短

import glob
from natsort import natsorted
from moviepy.editor import VideoFileClip, concatenate_videoclips
import glob
import os.path
 
from natsort import natsorted
import cv2
import imageio
 
if __name__ == '__main__':
    #內(nèi)存
    base_dir =r"C:\Users\Administrator\Videos\shuiyin\0127"
    base_dir =r'C:\Users\Administrator\Videos\shuiyin\result'
    output_path = "pinjie_shuiyin.mp4"
    video_paths =glob.glob(base_dir +'/*.mp4')
    video_paths=natsorted(video_paths)
    imgs=[]
    res = []
    for file in video_paths:
        cap_a = cv2.VideoCapture(file)  # 打開視頻B
        fps = cap_a.get(cv2.CAP_PROP_FPS)
        frame_count = 0
        print(file)
        while True:
            ret, frame_a = cap_a.read()
            if not ret:
                break  # 如果沒有讀取到幀,則跳出循環(huán)
            res.append(cv2.cvtColor(frame_a, cv2.COLOR_BGR2RGB))
            frame_count += 1  # 釋放視頻資源
        cap_a.release()
    imageio.mimsave(output_path, res, "mp4", fps=fps, macro_block_size=None)
 

方法三:

使用FFmpeg進(jìn)行視頻拼接,主要以兩個文件為例進(jìn)行合并,并且只轉(zhuǎn)換其中的視頻流

vector<string> fileList = { url_origin,url_add };//這是兩個文件
//獲得原始輸入視頻文件編碼等信息
const AVOutputFormat* ofmt = NULL;//輸出格式
AVFormatContext* ifmt_ctx = NULL, * ofmt_ctx = NULL;//視頻數(shù)據(jù)維護(hù)對象
AVPacket* pkt = NULL;//數(shù)據(jù)包

int ret;//函數(shù)執(zhí)行返回碼
int stream_index;//數(shù)據(jù)流索引

pkt = av_packet_alloc();//初始化數(shù)據(jù)包結(jié)構(gòu)
if (!pkt)
{
	return;
}

if ((ret = avformat_open_input(&ifmt_ctx, url_origin, 0, 0) < 0))
{
	goto end;//打開文件失敗
}

//獲得輸出文件名
string out_file;
auto name = ifmt_ctx->iformat->name;//自動識別文件的封裝類型
//hevc只能使用MP4或者h(yuǎn)evc封裝才能完成轉(zhuǎn)換,其余封裝報(bào)錯,因?yàn)檫@里進(jìn)行了自動識別可以不用管具體格式
out_file.replace(out_file.find('.')+1, 3, name);
const char* out_filename = out_file.c_str();

//根據(jù)第一個文件獲得其中的編碼等參數(shù),這里要求兩個文件的編碼格式一樣就是因?yàn)樵趯懭胛募r用的是相同的配置沒有進(jìn)行轉(zhuǎn)碼等操作
if ((ret = avformat_find_stream_info(ifmt_ctx, 0)) < 0)
{
	goto end;
}

avformat_alloc_output_context2(&ofmt_ctx, NULL, NULL, out_filename);
if (!ofmt_ctx)
{
	goto end;
}

ofmt = ofmt_ctx->oformat;
//查找視頻流并復(fù)制視頻流的參數(shù)到輸出流
for (int i = 0; i < ifmt_ctx->nb_streams; ++i)
{
	AVStream* in_stream = ifmt_ctx->streams[i];
	AVCodecParameters* in_codecpar = in_stream->codecpar;
	if (in_codecpar->codec_type != AVMEDIA_TYPE_VIDEO)//非視頻流跳過
	{
		continue;
	}
	AVStream* out_stream = avformat_new_stream(ofmt_ctx, NULL);//創(chuàng)建輸出流
	if (!out_stream)
	{
		goto end;
	}
	ret = avcodec_parameters_copy(out_stream->codecpar, in_codecpar);//復(fù)制解碼器參數(shù)
	if (ret < 0)
	{
		goto end;
	}
	out_stream->time_base = in_stream->time_base;//復(fù)制時間基
	stream_index = i;
	out_stream->codecpar->codec_tag = 0;
	break;
}
avformat_close_input(&ifmt_ctx);//關(guān)閉文件

//打開輸出文件
if (!(ofmt->flags & AVFMT_NOFILE))
{
	ret = avio_open(&ofmt_ctx->pb, out_filename, AVIO_FLAG_WRITE);
	if (ret < 0)
	{
		goto end;
	}
}

ret = avformat_write_header(ofmt_ctx, NULL);//寫入頭信息,如編碼等內(nèi)容
if (ret < 0)
{
	goto end;
}

int64_t i = 0;//用于計(jì)算時間戳,同時也是幀數(shù)
int64_t p_max_dts = 0;//用于拼文件的時間戳

for (int index = 0; index < fileList.size(); ++index)//遍歷文件
{
	if ((ret = avformat_open_input(&ifmt_ctx, fileList[index].c_str(), 0, 0)) < 0)
	{
		goto end;
	}

	if ((ret = avformat_find_stream_info(ifmt_ctx, 0)) < 0)//查找文件流信息
	{
		goto end;
	}

	//對流直接進(jìn)行轉(zhuǎn)寫
	while (1)
	{
		AVStream* in_stream, * out_stream;
		ret = av_read_frame(ifmt_ctx, pkt);
		if (ret < 0)
		{
			break;
		}
		pkt->stream_index = stream_index;//視頻流編號
		//這里做一個提示,因?yàn)樯鲜龅睦又挥幸曨l沒有音頻所以不會越界,如果存在多種流的這里需要看一下你new了幾個流,是否會越界
		in_stream = ifmt_ctx->streams[stream_index];
		out_stream = ofmt_ctx->streams[stream_index];

		//這里要對時間戳進(jìn)行處理,否則寫入的時候會失敗
		//單幀時長
		int64_t frameDuration = av_rescale_q(1, av_inv_q(in_stream->time_base), in_stream->r_frame_rate);
		//將單幀的時間從輸入流轉(zhuǎn)化到輸出流時間
		int64_t _t = av_rescale_q(frameDuration, in_stream->time_base, out_stream->time_base);

		//計(jì)算時間戳,并進(jìn)行累計(jì)以推算后面的時間戳
		p_max_dts = _t * (i);
		pkt->dts = p_max_dts;
		pkt->pts = pkt->dts;
		
		//如果音視頻都需要寫入可能需要這個函數(shù):av_interleaved_write_frame,他會進(jìn)行交叉寫入
		//pkt現(xiàn)在是空的,這個函數(shù)會獲得pkt內(nèi)容的所有權(quán)并重置,因此不需要unref,但是write_frame情況不同,需要手動釋放
		ret = av_write_frame(ofmt_ctx, pkt);//直接將包寫入輸出文件不進(jìn)行解碼
		av_packet_unref(pkt);
		if (ret < 0)
		{
			break;
		}
		++i;
	}

	//關(guān)閉文件
	avformat_close_input(&ifmt_ctx);
}

av_write_trailer(ofmt_ctx);//寫文件尾

end:
	av_packet_free(&pkt);//這里傳指針,因?yàn)橐獙kt設(shè)為null
	avformat_close_input(&ifmt_ctx);//同理
	if (ofmt_ctx && !(ofmt->flags & AVFMT_NOFILE))
	{
		avio_closep(&ofmt_ctx->pb);//avio打開要釋放
	}
	avformat_free_context(ofmt_ctx);
	if (ret < 0 && ret != AVERROR_EOF)
	{
		return;//異常結(jié)束
	}

這個示例可以完成視頻流的復(fù)制拼接,是一個比較簡單的示例,要求文件編碼等信息必須一致,不進(jìn)行轉(zhuǎn)碼,速度比較快。

到此這篇關(guān)于使用Python實(shí)現(xiàn)視頻拼接效果的文章就介紹到這了,更多相關(guān)Python視頻拼接內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Django REST framework 限流功能的使用

    Django REST framework 限流功能的使用

    DRF常用功能的案例基本用法都有講解,關(guān)于限流(Throttling)這個功能其實(shí)在真實(shí)的業(yè)務(wù)場景中能真正用到的其實(shí)不算多。今天說這個話題其實(shí)一方面是討論功能,另一方面也是希望換個角度去審視我們的開發(fā)過程,希望大家可以在使用DRF功能的同時,也了解一下功能背后的實(shí)現(xiàn)
    2021-06-06
  • Python3 replace()函數(shù)使用方法

    Python3 replace()函數(shù)使用方法

    這篇文章主要介紹了Python3 replace()函數(shù)使用方法,需要的朋友可以參考下
    2018-03-03
  • Python函數(shù)裝飾器常見使用方法實(shí)例詳解

    Python函數(shù)裝飾器常見使用方法實(shí)例詳解

    這篇文章主要介紹了Python函數(shù)裝飾器常見使用方法,結(jié)合實(shí)例形式分析了Python函數(shù)裝飾器的概念、原理、用法及相關(guān)操作注意事項(xiàng),需要的朋友可以參考下
    2019-03-03
  • 用Python的pandas框架操作Excel文件中的數(shù)據(jù)教程

    用Python的pandas框架操作Excel文件中的數(shù)據(jù)教程

    這篇文章主要介紹了用Python的pandas框架操作Excel文件中的數(shù)據(jù)教程,包括單位格式轉(zhuǎn)換、分類匯總等基本操作,需要的朋友可以參考下
    2015-03-03
  • Python模擬脈沖星偽信號頻率實(shí)例代碼

    Python模擬脈沖星偽信號頻率實(shí)例代碼

    這篇文章主要介紹了Python模擬脈沖星偽信號頻率實(shí)例代碼,具有一定借鑒價值,需要的朋友可以參考下
    2018-01-01
  • Python采集C站熱榜數(shù)據(jù)實(shí)戰(zhàn)示例

    Python采集C站熱榜數(shù)據(jù)實(shí)戰(zhàn)示例

    這篇文章主要為大家介紹了Python采集C站熱榜數(shù)據(jù)實(shí)戰(zhàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-05-05
  • python中文件變化監(jiān)控示例(watchdog)

    python中文件變化監(jiān)控示例(watchdog)

    這篇文章主要介紹了python中文件變化監(jiān)控示例(watchdog),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-10-10
  • python3+PyQt5實(shí)現(xiàn)文檔打印功能

    python3+PyQt5實(shí)現(xiàn)文檔打印功能

    這篇文章主要為大家詳細(xì)介紹了python3+PyQt5實(shí)現(xiàn)文檔打印功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-04-04
  • python從list列表中選出一個數(shù)和其對應(yīng)的坐標(biāo)方法

    python從list列表中選出一個數(shù)和其對應(yīng)的坐標(biāo)方法

    今天小編就為大家分享一篇python從list列表中選出一個數(shù)和其對應(yīng)的坐標(biāo)方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-07-07
  • 利用Python檢測URL狀態(tài)

    利用Python檢測URL狀態(tài)

    最近小編接到這樣的需求,Python檢測URL狀態(tài),并追加保存200的URL。接下來通過實(shí)例代碼給大家分析講解,需要的朋友跟隨小編一起看看吧
    2019-07-07

最新評論