胡斌

merge the audio file and video file according to the recordinfo


Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013
VisualStudioVersion = 12.0.31101.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "merge_av", "merge_av\merge_av.vcxproj", "{F607DD90-3E62-40BA-BF8A-185E597D646D}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{F607DD90-3E62-40BA-BF8A-185E597D646D}.Debug|Win32.ActiveCfg = Debug|Win32
{F607DD90-3E62-40BA-BF8A-185E597D646D}.Debug|Win32.Build.0 = Debug|Win32
{F607DD90-3E62-40BA-BF8A-185E597D646D}.Release|Win32.ActiveCfg = Release|Win32
{F607DD90-3E62-40BA-BF8A-185E597D646D}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
... ...
========================================================================
控制台应用程序:merge_av 项目概述
========================================================================
应用程序向导已为您创建了此 merge_av 应用程序。
本文件概要介绍组成 merge_av 应用程序的每个文件的内容。
merge_av.vcxproj
这是使用应用程序向导生成的 VC++ 项目的主项目文件,其中包含生成该文件的 Visual C++ 的版本信息,以及有关使用应用程序向导选择的平台、配置和项目功能的信息。
merge_av.vcxproj.filters
这是使用“应用程序向导”生成的 VC++ 项目筛选器文件。它包含有关项目文件与筛选器之间的关联信息。在 IDE 中,通过这种关联,在特定节点下以分组形式显示具有相似扩展名的文件。例如,“.cpp”文件与“源文件”筛选器关联。
merge_av.cpp
这是主应用程序源文件。
/////////////////////////////////////////////////////////////////////////////
其他标准文件:
StdAfx.h, StdAfx.cpp
这些文件用于生成名为 merge_av.pch 的预编译头 (PCH) 文件和名为 StdAfx.obj 的预编译类型文件。
/////////////////////////////////////////////////////////////////////////////
其他注释:
应用程序向导使用“TODO:”注释来指示应添加或自定义的源代码部分。
/////////////////////////////////////////////////////////////////////////////
... ...
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <iostream>
#include <fstream>
#include <vector>
bool only_print = false;
using namespace std;
class fileinfo {
public:
float start_time;
float end_time;
string start_time_str;
string end_time_str;
string name;
};
enum media_type{
type_audio = 0,
type_video = 1,
};
vector<fileinfo> media_files[2];
void run_shell_cmd(char * cmd)
{
if (only_print){
printf("\n%s", cmd);
}
else {
system(cmd);
}
}
char * default_vcodec_param = " -vcodec libx264 -level 3.1 -preset veryfast -g 40 -r 20 ";
char * default_acodec_param = " -acodec copy ";
char vcodec_param[1024];
char acodec_param[1024];
void addinfo( string t, string name, bool bstart ){
media_type mtype = name.substr(name.length() - 4, name.length()) == ".aac" ? type_audio : type_video;
if (bstart) {
fileinfo f;
f.start_time = atof(t.c_str());
f.end_time = f.start_time;
f.start_time_str = t;
f.end_time_str = t;
f.name = name;
media_files[mtype].push_back(f);
}
else {
vector<fileinfo> & files = media_files[mtype];
int i;
for (i = 0; i < files.size(); i++) {
if (files[i].name == name) {
files[i].end_time = atof(t.c_str());
files[i].end_time_str = t;
break;
}
}
if (i == files.size())
{
cout << "\nerror ,file : " << name << " close but not started!";
}
}
}
void split(string str, string separator, vector<string> &result, bool includeEmptyItem = false) {
result.clear();
string::size_type position = str.find(separator);
string::size_type lastPosition = 0;
int separatorLength = separator.length();
while (position != str.npos) {
string s = str.substr(lastPosition, position - lastPosition);
if (!s.empty() || includeEmptyItem)
result.push_back(s);
lastPosition = position + separatorLength;
position = str.find(separator, lastPosition);
}
result.push_back(str.substr(lastPosition, string::npos));
}
void split_audio(fileinfo audio, float audio_start, float duration, int nf)
{
char buf[2048];
sprintf(buf, "ffmpeg -y -i %s -ss %.3f -t %.3f %s %d_%s", audio.name.c_str(), audio_start, duration, acodec_param, nf, audio.name.c_str());
run_shell_cmd(buf);
}
void get_video_firstframe(fileinfo video)
{
char buf[2048];
sprintf(buf, "ffmpeg -y -i %s -vframes 1 -ss 0 -f mjpeg -an %s.jpg", video.name.c_str(), video.name.c_str());
run_shell_cmd(buf);
}
void merge_audio_pic(fileinfo audio, int nf, fileinfo video, char * destfile)
{
char buf[2048];
sprintf(buf, "ffmpeg -y -loop 1 -i %s.jpg -i %d_%s -loop 0 -shortest %s %s %s", video.name.c_str(), nf, audio.name.c_str(),acodec_param, vcodec_param, destfile);
run_shell_cmd(buf);
}
void megre_audio_video(fileinfo audio, int nf, fileinfo video, char * destfile)
{
char buf[2048];
sprintf(buf, "ffmpeg -y -i %d_%s -i %s %s %s %s", nf, audio.name.c_str(), video.name.c_str(), acodec_param, vcodec_param, destfile);
run_shell_cmd(buf);
}
void concate_files(vector<string > merged_files)
{
char buf[2048];
#ifdef WIN32
sprintf(buf, "copy /B %s ", merged_files[0].c_str());
for (int i = 1; i < merged_files.size(); i++) {
strcat(buf, " + /B ");
strcat(buf, merged_files[i].c_str());
}
#else
strcpy(buf, "cat ");
for (int i = 0; i < merged_files.size(); i++) {
strcat(buf, " ");
strcat(buf, merged_files[0].c_str());
}
strcat(buf ">");
#endif // WIN32
strcat(buf, " m.ts");
run_shell_cmd(buf);
}
void adjust_dest_timecode()
{
run_shell_cmd("ffmpeg -y -i m.ts -acodec copy -vcodec copy dest.ts");
}
int process_files()
{
vector<fileinfo> & filesaudio = media_files[type_audio];
vector<fileinfo> & filesvideo = media_files[type_video];
vector<string > merged_files;
int nv = 0;
int nf = 0;
char destfile[1024];
for (int i = 0; i < filesaudio.size(); i++){ //
fileinfo audio = filesaudio[i];
float audio_start = 0;
for (; nv < filesvideo.size(); nv++) {
fileinfo video = filesvideo[nv];
if (video.start_time - audio_start > 0.100) {
split_audio(audio, audio_start, video.start_time - audio_start, nf);
audio_start = video.start_time;
get_video_firstframe(video);
sprintf(destfile, "%d.ts", nf);
merge_audio_pic(audio, nf, video, destfile);
merged_files.push_back(destfile);
nf++;
}
if (nv != filesvideo.size() - 1) {// not the last one
split_audio(audio, video.start_time, video.end_time - video.start_time, nf);
audio_start = video.end_time;
sprintf(destfile, "%d.ts", nf);
megre_audio_video(audio, nf, video, destfile);
merged_files.push_back(destfile);
nf++;
}
else {
split_audio(audio, video.start_time, audio.end_time - video.start_time, nf);
audio_start = video.end_time;
sprintf(destfile, "%d.ts", nf);
megre_audio_video(audio, nf, video, destfile);
merged_files.push_back(destfile);
nf++;
}
}
}
concate_files(merged_files);
adjust_dest_timecode();
return 0;
}
int readfile(char * filename)
{
ifstream fin(filename);
if (!fin) {
return -1;
}
const int LINE_LENGTH = 1000;
char str[LINE_LENGTH];
while (fin.getline(str, LINE_LENGTH))
{
vector < string > res;
split(str, " ", res);
if (res.size() >= 3) {
if (res[2] == "create"){
addinfo(res[0], res[1], true);
}
else if (res[2] == "close") {
addinfo(res[0], res[1], false);
}
}
}
return 0;
}
void load_codec_param()
{
strcpy(acodec_param, default_acodec_param);
strcpy(vcodec_param, default_vcodec_param);
}
int main(int argc, char * argv[])
{
if (argc < 2) {
printf("%s record_info_filename [-p]");
return -1;
}
if (readfile(argv[1]) < 0) {
printf("open file: %s error", argv[1]);
return -2;
}
if (argc == 3 && !strcmp(argv[2], "-p")) {
only_print = true;
}
load_codec_param();
process_files();
return 0;
}
... ...
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{F607DD90-3E62-40BA-BF8A-185E597D646D}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>merge_av</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions> _CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>Use</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions> _CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<Text Include="ReadMe.txt" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="merge_av.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
</ClCompile>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
\ No newline at end of file
... ...
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="源文件">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="头文件">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="资源文件">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<Text Include="ReadMe.txt" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="merge_av.cpp">
<Filter>源文件</Filter>
</ClCompile>
</ItemGroup>
</Project>
\ No newline at end of file
... ...