通过FFmpeg 来筛选合并视频文件的项目记录

这篇具有很好参考价值的文章主要介绍了通过FFmpeg 来筛选合并视频文件的项目记录。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

项目需求

平台通过http下发json格式的消息

程序收到消息后 根据日期时间戳去对应的目录检索是否符合要求的文件 比如某个时间段

检索到之后 将视频片段拼接成一个完整的视频文件 

没有的话 根据时间戳判断是否需要等待或者 返回没有检索到 

头文件

#ifndef QMCY_LED_H
#define QMCY_LED_H

#include <iostream>
#include <atomic>
#include<vector>
#include<unordered_map>
#include<map>

#include<tuple>
#include <thread>
#include <memory>
#include <mutex>
#include <vector>



#include <semaphore.h>
#include <signal.h>
#include <condition_variable>


#include "zlog.h"

#include "httplib.h"
#include "json.hpp"
#include "BlockQueue.hpp"
#include "BlackBox.h"



#define HTTP_PORT	8081
#define HTTP_IP	"0.0.0.0"

#define 		MAX_THREADS	2
#define 		MAX_QUEUE_SIZE 4

#define DEVICE_VERSION	"VIDEO FILETER 1.0"




#define HTTP_SEARCH	"/api/search"


typedef enum
{
	MSG_SET_CONTENT,
	MSG_UPDATE_LED_LIST,
	MSG_EXIT_LED
}MSG_ID;



struct INNER_MSG
{
	MSG_ID msg_id;

	std::string taskid;
	std::string date;
	std::string time;
	int total_time;
};



typedef struct {

	std::string server_ip_name;
	std::string server_port_name;
	std::string local_port_name;


	std::string server_ip;
	std::string local_ip;
	std::string device_id;
	int server_port;
	int local_port;	
	bool debug_mode;
	bool encrypt_mode;
}AppBasicInfo;



template<class Typename>
class HANA 
{
	public:
		/**
		 * @brief 返回单例智能指针
		 */
		static std::shared_ptr<Typename> GetHANA()
		{

			static std::shared_ptr<Typename> object (new Typename);
			std::cout<<__func__<<" "<<object.use_count()<<std::endl;					
			std::cout<<__func__<<"address "<<&object<<std::endl;								
			return object;
		}
	private:
		HANA();
};




class semaphore {
public:
    explicit semaphore(size_t initial = 0) {
#if defined(HAVE_SEM)
        sem_init(&_sem, 0, initial);
#else
        _count = 0;
#endif
    }

    ~semaphore() {
#if defined(HAVE_SEM)
        sem_destroy(&_sem);
#endif
    }

    void post(size_t n = 1) {
#if defined(HAVE_SEM)
        while (n--) {
            sem_post(&_sem);
        }
#else
        std::unique_lock<std::recursive_mutex> lock(_mutex);
        _count += n;
        if (n == 1) {
            _condition.notify_one();
        } else {
            _condition.notify_all();
        }
#endif
    }

    void wait() {
#if defined(HAVE_SEM)
        sem_wait(&_sem);
#else
        std::unique_lock<std::recursive_mutex> lock(_mutex);
        while (_count == 0) {
            _condition.wait(lock);
        }
        --_count;
#endif
    }

private:
#if defined(HAVE_SEM)
    sem_t _sem;
#else
    size_t _count;
    std::recursive_mutex _mutex;
    std::condition_variable_any _condition;
#endif
};



class QMCY_APP:public std::enable_shared_from_this<QMCY_APP>
{
public:
	using PTR = std::shared_ptr<QMCY_APP>;
	//using LED_TABLE = std::unordered_map<std::string,std::shared_ptr<IModuleNVR>>;

	QMCY_APP();
	~QMCY_APP();

	void Version();

	bool Init(std::string &config_file, char *env[]);
	bool Start();	
	bool  Stop();



private:
	uint64_t m_counter;
	std::atomic<bool>m_run_flag;
	AppBasicInfo m_basic_info;
	std::thread m_http_thread;
	std::thread m_task_thread;
	std::thread m_timer_thread;	


	std::mutex m_table_mutex;


	httplib::Server m_http;
	

	void MainTask();
	void  HttpTask();	
	void TimerTask();	

	void DispatchTask(INNER_MSG inner_msg);
	void RealExecUnit(INNER_MSG inner_msg);
	
	void Report();

	void ParseSearch(const std :: string & json);

	std::vector<std::string> GetFiles(std::string dir,std::string time);
	void ReadConfig(const std::string &json);	
	
	std::shared_ptr<httplib::Client> m_http_client;

	std::shared_ptr<BlockQueue<INNER_MSG>>	m_inner_queue;	
	
	std::shared_ptr<BlackBox> m_thread_pool;
	
};


#endif 

cpp文件

#include "QMCY_DUMP.h"
#include <sys/types.h>
#include <dirent.h>



static semaphore sem;

zlog_category_t *g_zlog;


QMCY_APP::QMCY_APP()
{
	m_counter = 0;

	std::cout<<__func__<<std::endl;
}


QMCY_APP::~QMCY_APP()
{
	std::cout<<__func__<<std::endl;	
}


  void QMCY_APP::Version()
  {
  	std::cout<<"Version 1.0"<<std::endl;
  }






std::vector<std::string> QMCY_APP::GetFiles(const std::string dir,std::string time)
{

	int hour,minute,second,sn;
	int converted;
	unsigned int last_item_time = 0;
	int check_times = 0;
	
	std::vector<std::string> result;
	std::map<unsigned int,std::string> table;
	unsigned int keyword;
	char path[1000];
	strcpy(path,dir.c_str());
	DIR *dp;
	struct dirent *files;
	/*structure for storing inode numbers and files in dir
	struct dirent
	{
	  ino_t d_ino;
	  char d_name[NAME_MAX+1]
	}
	*/


	RECHECK:

	result.clear();
	table.clear();
	
	check_times++;

	
	if((dp=opendir(path))==NULL)
	  perror("dir\n");
	char newp[1000];
	struct stat buf;
	while((files=readdir(dp))!=NULL)
	{
		if(!strcmp(files->d_name,".") || !strcmp(files->d_name,".."))
		 continue;

		strcpy(newp,path);
		strcat(newp,"/");
		strcat(newp,files->d_name); 
		//printf("%s\n",newp);

		//printf("%s\n",files->d_name);

		std::string filename = files->d_name;
		std::size_t found = filename.find_last_of(".mp4");
		if(found == filename.size() -1)
		{
			//printf("find :%d\n",found);


			converted = sscanf(files->d_name, "%02d-%02d-%02d-%d", &hour, &minute, &second,&sn);
			if(converted == 4)
			{
				unsigned int key = hour*3600+minute*60+second;
				table.insert(std::pair<unsigned int,std::string>(key,files->d_name));
			}

		}
		else
		{
			printf("not a mp4 file\n");
			continue;
		}

	}


	

	converted = sscanf(time.c_str(), "%02d:%02d:%02d", &hour, &minute, &second);



	

	if(converted == 3)
	{
		keyword = 		hour*3600+minute*60+second;
		std::cout<<"keyword is:"<<keyword<<std::endl;
		for(auto &item:table)
		{
			if(item.first>=keyword-6 && item.first <=keyword+6)
			{
				std::cout<<"matched :"<<item.first<<"----->"<<item.second<<std::endl;
				result.push_back(item.second);

			}
			else
			{
				std::cout<<"Unmatched :"<<item.first<<"----->"<<item.second<<std::endl;			
			}
			
			last_item_time = item.first;			
		}



	}

	std::cout<<"last_item_time:"<<last_item_time <<" check_times:"<<check_times<<std::endl; 	


	if( last_item_time <= keyword+6 && check_times <= 15)
	{
		sleep(1);
		std::cout<<"Recheck files!!!"<<std::endl;		

		goto RECHECK;
	}


	return result;
}

void QMCY_APP::RealExecUnit(INNER_MSG inner_msg)
{
	//std::this_thread::sleep_for(std::chrono::seconds(10));

	
	//std::cout<<"long time task complete:"<<std::this_thread::get_id()<<std::endl;

	zlog_info(g_zlog,"Date: [%s] time:[%s]",inner_msg.date.c_str(),inner_msg.time.c_str());


	std::vector<std::string> files = GetFiles(inner_msg.date,inner_msg.time);

	std::string filecontent;

	if(files.size() >0)
	{
		for(auto &item:files)
		{
				std::cout<<"matched :"<<item<<std::endl;
				filecontent+="file ";
				filecontent+="'";
				filecontent+=inner_msg.date;
				filecontent+="/";
				filecontent+=item;				
				filecontent+="'\r\n";				
		}


		zlog_info(g_zlog,"Search result:[%s]",filecontent.c_str());


		std::string filename =std::to_string( rand());

		FILE * fp = fopen(filename.c_str(),"w");
		if(fp)
		{
			fwrite(filecontent.c_str(),1,filecontent.size(),fp);
			fclose(fp);
		}

		//Use ffmpeg to concat two or more videos to one video
		//ffmpeg command : ./ffmpeg -f concat -safe 0 -i 363974492 -c:v copy -c:a aac 2023-06-29/363974492.mp4 

		std::string ffmpeg_cmd = "./ffmpeg -f concat -safe 0 -i ";
		ffmpeg_cmd+= filename;
		ffmpeg_cmd+=" -c:v copy -c:a aac ";
		ffmpeg_cmd+=inner_msg.date;
		ffmpeg_cmd+="/";
		ffmpeg_cmd+=filename;
		ffmpeg_cmd+=".mp4";		

		auto ret = system(ffmpeg_cmd.c_str());

		std::cout<<"ffmpeg:"<<ffmpeg_cmd<<" result:"<<ret<<std::endl;
		if(ret == 0)
		{
			zlog_info(g_zlog,"Concat videos successfully, output file is  :[%s.mp4]",filename.c_str());
			//Success
		}
		else
		{
			zlog_info(g_zlog,"Concat video failed!!!!");		
			//Error
		}

		char temp_cmd [100] = {0};

		strcat(temp_cmd,"rm ");
		strcat(temp_cmd,filename.c_str());
		system(temp_cmd);
		
	}
	else
	{
		std::cout<<"No match files"<<std::endl;
		zlog_info(g_zlog,"Concat video No match files!!!!");				
	}
	
	
}


void QMCY_APP::DispatchTask(INNER_MSG inner_msg)
{

	auto size = m_thread_pool->get_tasks();

	if(size >= MAX_QUEUE_SIZE)
	{
		//Need to tell server this task can not be exectued!!!!!
		std::cout<<"Task full   add failed  task size "<<size<<std::endl;										

		zlog_info(g_zlog,"System is busy  can not handle this command!!!!!");
		
		return ;
	}


	m_thread_pool->AddTask([this,inner_msg](){
		RealExecUnit(inner_msg);
	});	

	//std::cout<<" DispatchTask AddTask Exit !!!!!!!!!!!"<<std::endl;						
		
}

void QMCY_APP::MainTask()
{
	INNER_MSG inner_msg;

	while(true)
	{
		bool ret = m_inner_queue->pop_data(inner_msg); 
		if(ret )
		{
			if(MSG_EXIT_LED == inner_msg.msg_id)
			{
				std::cout<<"Get exit msg :"<<inner_msg.msg_id<<std::endl;						
				break;
			}
			else if(MSG_SET_CONTENT == inner_msg.msg_id)
			{
				DispatchTask(inner_msg);
			}
		}
	}

	std::cout<<__func__<<" exit!!!!"<<std::endl;
}


void QMCY_APP::Report()
{

	std::unique_lock<std::mutex> lock(m_table_mutex);

	jsonxx::json response ;
#if 0
	for(auto it=m_led_table.begin(); it!=m_led_table.end();it++)
	{

		jsonxx::json item;

		auto led   = it->second;

		if(m_run_flag.load() == false || led == nullptr)
		{
			return;
		}

		auto result = led ->NVR_GetStatus();

		item["bmsid"]= it->first;
		item["status"]= result.first;
		item["msg"]= result.second;
		
		response.push_back(std::move(item));

	}

	auto output = response.dump();
	if(output.size())
	{
		std::cout<<"Report content:"<<output<<std::endl;
		if(auto res = m_http_client->Post("/qmcy",output,"application/json"))
		{
			if (res->status == 200)
			{
				
			}
			else
			{
				auto err = res.error();
				std::cout << "HTTP error: " << httplib::to_string(err) << std::endl;
			}
	
		}
		else
		{
			std::cout<<"Report status to server  failed!"<<std::endl;
			//zlog_error(g_zlog,"Report status to server[%s:%d]  failed!",pHandle->server_ip,pHandle->server_port);
		}
	}
#endif	

}



void QMCY_APP::TimerTask()
{

	while(m_run_flag.load())
	{
		m_counter++;
		if(m_counter % 200 == 0)
		{
			if(m_run_flag.load())
			{
				Report();
			}

		}
		std::this_thread::sleep_for(std::chrono::seconds(1));
	}

	std::cout<<__func__<<" exit!!!"<<std::endl;
}



void QMCY_APP::ParseSearch(const std :: string & json)
{
	jsonxx::json result;

	INNER_MSG inner_msg;
	
	try
	{
		result = jsonxx::json::parse(json);			
	}
	catch (jsonxx::json_parse_error & err)
	{
		std::cout<<"Json parse failed" <<std::endl;			
		return;
	}
	
	if(result["taskid"].is_string())
	{
		inner_msg.taskid = result["taskid"].as_string();
	}

	if(result["date"].is_string())
	{
		inner_msg.date = result["date"].as_string();
	}

	if(result["time"].is_string())
	{
		inner_msg.time = result["time"].as_string();
	}

	if(result["total_time"].is_integer())
	{
		inner_msg.total_time = result["total_time"].as_int();
		if(inner_msg.total_time <1 || inner_msg.total_time >20)
		{
			inner_msg.total_time = 10;
		}
	}


	inner_msg.msg_id = MSG_SET_CONTENT;
	m_inner_queue->push_data(inner_msg);
}




void QMCY_APP::HttpTask()
{

	m_http.Get("/hi", [](const httplib::Request &, httplib::Response &res) {
	  res.set_content("Hello World!", "text/plain");
	});


	m_http.Get("/led/status", [](const httplib::Request &, httplib::Response &res) {
	  res.set_content("Get led status World!", "text/plain");
	});


	m_http.Post("/Stop", [](const httplib::Request &req, httplib::Response &res) {
		  res.set_content("PostLEDConfig message!", "text/plain");
	  		std::cout<<"APP exit message"<<std::endl;
			sem.post();		
		});


	m_http.Post(HTTP_SEARCH, [&](const httplib::Request &req, httplib::Response &res) {
	  res.set_content(HTTP_SEARCH, "text/plain");
		//std::cout<<req.body<<std::endl;		

		ParseSearch(req.body);
	  
	});

	std::cout<<__FUNCTION__<<std::endl;


	auto ret =   m_http.listen("0.0.0.0", m_basic_info.local_port);
	if(ret == false)
	{
		std::cout<<"Http failed"<<std::endl;
		sem.post();		
	}
	else
	{
		std::cout<<"Http success"<<std::endl;
	}

	std::cout<<__func__<<" exit!!!"<<std::endl;

}



void QMCY_APP::ReadConfig(const std :: string & data)
{
	jsonxx::json result;

	try
	{
		result = jsonxx::json::parse(data); 		
	}
	catch (jsonxx::json_parse_error & err)
	{
		std::cout<<"ReadConfig Json parse failed" <<std::endl;			
		return;
	}

	if(result["sn"].is_string())
	{
		m_basic_info.device_id = result["sn"].as_string(); 	
	}

	if(result["server_ip_name"].is_string())
	{
		m_basic_info.server_ip_name = result["server_ip_name"].as_string(); 	
	}

	if(result["server_port_name"].is_string())
	{
		m_basic_info.server_port_name = result["server_port_name"].as_string(); 	
	}

	if(result["local_port_name"].is_string())
	{
		m_basic_info.local_port_name = result["local_port_name"].as_string(); 	
	}
	
}


bool QMCY_APP::Init(std::string &config_file, char *env[])
{
	char *file_content = nullptr;
	int size = 0;

	unsigned seed = time(0);
	srand(seed);


	if(config_file.empty())
	{
		std::cout<<"config file is null"<<std::endl;
		return false;
	}
	
	FILE * fp = fopen(config_file.c_str(),"r");
	if(fp == NULL)
	{
		return false;
	}

	fseek(fp, 0, SEEK_END);
	size = ftell(fp);


	file_content = (char *)malloc(size+1);
	if(file_content)
	{
		fseek(fp, 0, SEEK_SET);
		fread(file_content,size,1,fp);

		ReadConfig(file_content);
		
		free(file_content);

	}
	
	fclose(fp);	




	int i = 0;
	char key[20] ={0},value[30]={0};
	
	for(; env[i]; i++){
		std::string temp = env[i];

		std::size_t found = temp.find(m_basic_info.server_ip_name);
		if(found!= std::string::npos)
		{
			int converted = sscanf(temp.c_str(),"%[^=]=%s",key,value);
			if(converted == 2)
			{
				m_basic_info.server_ip = value;				
			}
			
		}


		found = temp.find(m_basic_info.server_port_name);
		if(found!= std::string::npos)
		{
			int converted = sscanf(temp.c_str(),"%[^=]=%s",key,value);
			if(converted == 2)
			{
				m_basic_info.server_port = atoi(value);
			}

		}


		found = temp.find(m_basic_info.local_port_name);
		if(found!= std::string::npos)
		{
			int converted = sscanf(temp.c_str(),"%[^=]=%s",key,value);
			if(converted == 2)
			{
				//std::cout<<"local port :"<<key<<" :"<<value<<std::endl;
				m_basic_info.local_port = atoi(value);				
			}
		}


		
	}


	if(m_basic_info.local_port<1024|| m_basic_info.local_port >65535 )
	{
		m_basic_info.local_port = 8888;
	}

	if(m_basic_info.server_port<1024|| m_basic_info.server_port >65535 )
	{
		m_basic_info.server_port = 8888;
	}



	zlog_info(g_zlog,"APP run info:[server ip = %s,server port=%d, local port = %d]",m_basic_info.server_ip.c_str(),m_basic_info.server_port,m_basic_info.local_port);


	std::string posturi = "http://";
	posturi.append(m_basic_info.server_ip);
	posturi.append(":");	
	posturi.append(std::to_string(m_basic_info.server_port));	


	m_http_client = std::make_shared<httplib::Client>(posturi);

	//m_log = HANA<LOG>::GetHANA();

	m_thread_pool = std::make_shared<BlackBox>(MAX_THREADS,MAX_QUEUE_SIZE);
	m_thread_pool->init();

	m_inner_queue = std::make_shared<BlockQueue<INNER_MSG>>(30);

	return true;	
		
}



bool QMCY_APP::Start()
{

	m_run_flag = true;
	
	m_task_thread = std::thread(&QMCY_APP::MainTask,this);
	m_http_thread = std::thread(&QMCY_APP::HttpTask,this);	
	m_timer_thread = std::thread(&QMCY_APP::TimerTask,this);	



	//std::this_thread::sleep_for(std::chrono::seconds(1));

	zlog_info(g_zlog,"QMCY Video filter system successfully started");

	
	return true;
}


bool QMCY_APP::Stop()
{
	std::cout<<__func__<<std::endl;
	INNER_MSG inner_msg;


	inner_msg.msg_id = MSG_EXIT_LED;

	m_inner_queue->push_data(inner_msg);

	m_thread_pool->shutdown();
	

	m_run_flag = false;


	m_http.stop();


	m_task_thread.join();
	m_http_thread.join();
	if(m_timer_thread.joinable())
	{
		m_timer_thread.join();
	}


	return true;
}



void PrintLEDVersion()
{
	const char APP_time[] =  "QMCY VIDEO FILTER (build in: " __DATE__ " " __TIME__ ")";

	zlog_info(g_zlog,"=====================================================================================\n");
	zlog_info(g_zlog,"                     QMCY VIDEO FILTER system Version[%s], Date[%s]                  \n",DEVICE_VERSION, APP_time);
	zlog_info(g_zlog,"=====================================================================================\n"); 


	printf("程序版本[%s]\n",APP_time);

}




int main(int argc,char *argv[], char *env[])
{


	auto rc = zlog_init("./zlog.conf");
	if (rc) {
		printf("init failed\n");
		return false;
	}

	g_zlog = zlog_get_category("qmcy");
	if (!g_zlog) {
		printf("get cat fail\n");
		zlog_fini();
		return -1;
	}


	std::string config = "config.json";


	std::shared_ptr<QMCY_APP> app = HANA<QMCY_APP>::GetHANA();

	
	if(app->Init(config,env) == false) 
	{
		std::cout<<"APP init failed"<<std::endl;
		return -1;
	}


	std::cout<<"APP init success"<<std::endl;
	app->Start();


  signal(SIGINT, [](int) {
		std::cout << "GET QMCY exit signal SIGINT:exit";
		signal(SIGINT, SIG_IGN);// 设置退出信号
		sem.post();
  });// 设置退出信号

	sem.wait();

	app->Stop();

	std::cout<<"Exit QMCY APP system"<<std::endl;

	zlog_info(g_zlog,"Exit QMCY Video filter system ");

	
	return 0;
}


Http服务用cpphttp

项目中用到 线程池 等待队列 等 文章来源地址https://www.toymoban.com/news/detail-555320.html

到了这里,关于通过FFmpeg 来筛选合并视频文件的项目记录的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • ffmpeg——同时剪辑多个视频并合并

    基本语法 所用的ffmpeg的语法: 1.剪辑单个视频 ffmpeg -i [2021-11-24-1-2.mp4] -vcodec copy -acodec copy -ss [00:00:00] -to [00:00:05] [output/p3.mp4][ ]中三个参数依次为:剪辑视频源文件;第一个时间为剪辑的起始时间;第二个时间为视频持续的时间长度; 剪辑好的文件名 2.合并视频片段 ffmpeg -

    2024年02月16日
    浏览(44)
  • FFMPEG常用命令 音视频合并

            目录 一、音频合并 1.获取音频时长 2.合并两段音频 3.合并音频插入空白 二、视频加背景图 三、音视频合成 1.保留视频声音 2.不保留视频声音 四、合并视频         本文将用几个实例,介绍ffmpeg命令的综合使用,主要涉及音频处理、视频处理和音视频合成。 参数

    2024年02月10日
    浏览(72)
  • 使用ffmpeg合并视频遇到的坑

    下面以Linux环境介绍为主 1.ffmpeg可执行命令不同的环境是不同的,Linux在执行命令前还需要授权。 2.合并视频命令: 坑一:其中第一个花括号替换的是可执行命令所在的绝对路径,这里必须要使用ffmpeg的绝对路径,因为把应用打成jar包是无法获取到绝对路径的,具体可参考:

    2024年02月16日
    浏览(53)
  • ffmpeg合并多张图片为视频,加转场

    转场特效,可以在:https://trac.ffmpeg.org/wiki/Xfade#MP4output 查看 -stream_loop 输入流循环的次数,0 表示无循环,-1 表示无限循环,即音乐循环播放。 -acodec aac 设置音频编解码为 acc 模式 -map “[v]” 将合成的视频输入流 v 指定为输出文件的源 -map “5:a” 将第6个文件作为视频音频文件

    2024年02月16日
    浏览(64)
  • 如何使用 ffmpeg 对视频进行切分、合并

    1. 按照视频时间点进行截取, 起止点:00:00:06 ~ 00:20:36 ffmpeg -ss 00:00:06 -to 00:20:36 -accurate_seek -i \\\"input.mp4\\\" -avoid_negative_ts 1 -c copy \\\"ouput.mp4\\\" -y 2.  分离视频和音频 ffmpeg -i \\\"input.mp4\\\" -vcodec copy -an \\\"out-vod.mp4\\\" ffmpeg -i \\\"input.mp4\\\" -acodec copy -vn \\\"out-sound.m4a\\\"  3. 去除水印(指定区域模糊化,以

    2024年02月09日
    浏览(39)
  • 哔哩哔哩视频合并 B站缓存视频合并 安卓版 音视频合并 基于ffmpeg

    此软件是为了帮助网友合并哔哩哔哩缓存视频,Android上将bilibili缓存视频合并导出为mp4,你可以将它理解为一个专用的格式工厂,并不涉及破解相关内容,仅仅用于学习技术交流,严禁用于商业用途,如有侵权请联系我删档,对你带来困惑和不便我深感抱歉。 合并(导出)B站缓

    2024年02月02日
    浏览(73)
  • ffmpeg教程:视频切片与合并,加密与解密

    目录 1、ffmpeg安装教程         1.1 下载地址         1.2 ffmpeg环境配置 2、视频分割成ts文件         2.1 准备mp4文件         2.2 打开当前目录cmd命令窗口 3、根据m3u8文件合并ts文件         3.1 准备文件         3.2 输入命令 4、视频切片与加密         4.1 下载安装openssl  

    2024年02月08日
    浏览(50)
  • python使用ffmpeg合并多张图片成视频

    注意: 需要在本地有ffmpeg,并且配置环境变量 下载链接如下:https://download.csdn.net/download/qq_30273575/87898080 # FFmpeg 将多张图片合成视频 # 可以使用 FFmpeg 库来将多张图片合成视频,下面是一个简单的示例: # 在代码中,需要提供存储图片的文件夹路径 images_path 和最终生成的视频

    2024年02月11日
    浏览(50)
  • 监控视频片段合并完整视频|FFmpeg将多个视频片段拼接完整视频|PHP自动批量拼接合并视频

    关于环境配置ffmpeg安装使用的看之前文章 哔哩哔哩缓存转码|FFmpeg将m4s文件转为mp4|PHP自动批量转码B站视频

    2024年02月04日
    浏览(61)
  • ffmpeg综合应用示例(五)——多路视频合并(Linux版本)

    来源:微信公众号「编程学习基地」 本文的目的为方便Linux下编译运行多路视频合成Demo 原文:ffmpeg综合应用示例(五)——多路视频合并 Ubuntu 20.04 + ffmpeg version ffmpeg-4.4-x86_64 编译 Linux下修改后的代码

    2024年02月14日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包