胡斌

1.add -d to indicate output as individual video segment if the timeline is not continuous

2.support fill blank video with last video frame

1.8 KB | 宽: | 高:

1.8 KB | 宽: | 高:

  • 两方对比
  • 交换覆盖
  • 透明覆盖
... ... @@ -12,6 +12,7 @@
bool only_print = false;
bool keep_tmp_files = false;
bool out_one_video = true;
using namespace std;
enum media_type{
... ... @@ -57,6 +58,7 @@ vector<fileinfo> media_files;
const char * MERGED_PREFIX = "";
const char * PIP_PREFIX = "pip_";
float get_file_duration(const char *mediafile, bool bVideo);
void run_shell_cmd(const char * cmd)
{
... ... @@ -241,6 +243,7 @@ void get_video_first_frame_jpeg(const char * video, const char * destfile)
run_shell_cmd(buf);
}
void merge_audio_pic(const char * audio, const char * picfile, const char * destfile)
{
char buf[2048];
... ... @@ -274,7 +277,7 @@ void merge_audio_video(const char * audio, const char * video, int rotate, const
void merge_video_pip(const char * ch0, const char * ch1, const char * destfile)
{
char buf[2048];
sprintf(buf, "ffmpeg -i %s -i %s %s %s %s", ch0, ch1, pip_param, av_codec_param, destfile);
sprintf(buf, "ffmpeg -y -i %s -i %s %s %s %s", ch0, ch1, pip_param, av_codec_param, destfile);
run_shell_cmd(buf);
}
... ... @@ -382,7 +385,6 @@ float parse_ffmpeg_duration(const char * file)
if (hms.size() != 3) {
printf("\nerro parsing duration in %s, the duration string is:%s\n", file, content);
delete content;
return -1.0;
}
... ... @@ -568,7 +570,92 @@ char silence_aac_file[1024];
char out_info_file[1024];
FILE * fp_out_info = NULL;
void merge_pic_silence(const char * pic, float duration, const char * destfile)
{
char buf[2048];
sprintf(buf, "ffmpeg -y -loop 1 -i %s -i %s -loop 0 -t %.3f -shortest %s %s %s", pic, silence_aac_file, duration, acodec_param, vcodec_param, destfile);
run_shell_cmd(buf);
}
int parse_ffmpeg_lastframe(const char * file)
{
FILE * fp = fopen(file, "rb");
if (!fp) {
printf("\nOpen %s error\n", file);
return -1.0;
}
fseek(fp, 0l, SEEK_END);
long file_len = ftell(fp);
fseek(fp, 0l, SEEK_SET);
char * content = new char[file_len + 1];
fread(content, 1, file_len, fp);
fclose(fp);
content[file_len] = 0;
if (!keep_tmp_files) {
remove_file(file);
}
char * pLastFrame = strstr(content, "frame=");
if (!pLastFrame){
printf("\ncan't find 'frame' in %s\n", file);
delete content;
return 0;
}
while (1){
char * pFrame = strstr(pLastFrame + 6, "frame=");
if (!pFrame){
break;
}
pLastFrame = pFrame;
}
int frame = atoi(pLastFrame + 6);
delete content;
return frame;
}
void get_video_last_frame_jpeg(const char * video, const char * destfile) {
char buf[2048];
//first ,get
float duration = get_file_duration(video, true);
if (duration > 0) {
float start = 0;
if (duration > 1) {
start = duration - 1;
}
#ifdef WIN32
sprintf(buf, "ffmpeg -y -i %s -ss %.1f -an %s_last_%%d.jpg > %s.txt 2>&1", video, start, video,video);
#else
sprintf(buf, "ffmpeg -y -i %s -ss %.1f -an %s_last_%%d.jpg &> %s.txt", video, start, video, video);
#endif
run_shell_cmd(buf);
sprintf(buf,"%s.txt", video);
int last_frame = parse_ffmpeg_lastframe(buf);
if (last_frame > 0) {
#ifdef WIN32
sprintf(buf, "copy %s_last_%d.jpg %s", video,last_frame,destfile);
#else
sprintf(buf, "cp %s_last_%d.jpg %s", video, last_frame,destfile);
#endif
run_shell_cmd(buf);
for (int i = 1; i <= last_frame; i++) {
sprintf(buf, "%s_last_%d.jpg", video, i);
tmp_files.push_back(buf);
}
}
}
else {
#ifdef WIN32
sprintf(buf, "copy %s %s", blank_pic_file, destfile);
#else
sprintf(buf, "cp %s %s", blank_pic_file, destfile);
#endif
}
}
void add_media_info(media_info m)
{
... ... @@ -1190,12 +1277,25 @@ int get_output_file_name(int i, const char * filename, const char * prefix,char
return 0;
}
bool is_need_output(int nOutPutFile, vector<media_info> & cur_processing, const char * first_file, char * outputfile, const char * prefix="")
bool is_need_output(int & nOutPutFile, vector<media_info> & cur_processing, const char * first_file, char * outputfile, const char * prefix="")
{
if (sorted_infos.size()) {
int lastEnd = cur_processing[cur_processing.size() - 1].type_time;
int nextStart = sorted_infos.front().type_time;
if (nextStart - lastEnd < 0.2) {
float lastEnd = cur_processing[cur_processing.size() - 1].type_time;
float nextStart = sorted_infos.front().type_time;
float gap = nextStart - lastEnd;
if ( gap < 0.2) {
return false;
}
else if(out_one_video){
string last_merged_video = merged_files[merged_files.size() - 1];
char buf[1024];
sprintf(buf, "%s_last_frame.jpg", last_merged_video.c_str());
get_video_last_frame_jpeg(last_merged_video.c_str(), buf);
char buf_dest[1024];
sprintf(buf_dest, "%d.ts", nOutPutFile++);
merge_pic_silence(buf, gap, buf_dest);
merged_files.push_back(buf_dest);
tmp_files.push_back(buf);
return false;
}
}
... ... @@ -1380,7 +1480,7 @@ int process_merged_files_to_pip_files()
return 0;
}
int readfile(char * filename)
int readfile(const char * filename)
{
init_read_file();
media_files.clear();
... ... @@ -1454,7 +1554,7 @@ float get_start_time_from_filename(const char * filename)
vector<string> all_input_files_for_pip;
int readfile(char * filename, int channel)
int readfile(const char * filename, int channel)
{
init_read_file();
... ... @@ -1535,35 +1635,79 @@ void load_codec_param()
}
}
void get_outinfo_file_name(char * input1 , char * input2)
void get_outinfo_file_name(char * input)
{
strcpy(out_info_file, input1);
strcpy(out_info_file, input);
char * p = strstr(out_info_file, ".");
if (p) {
*p = 0;
}
strcat(out_info_file, "__");
strcat(out_info_file, input2);
strcat(out_info_file, "_out.txt");
}
void get_outinfo_file_name(char * input)
int process_record_info_to_ts(char * record_info, vector<string> & merged_info1, vector<string> & merged_info2)
{
strcpy(out_info_file, input);
char * p = strstr(out_info_file, ".");
if (p) {
*p = 0;
ifstream fin(record_info);
if (!fin) {
return -1;
}
strcat(out_info_file, "_out.txt");
const int LINE_LENGTH = 1000;
char str[LINE_LENGTH];
bool bInTeacher = false;
bool bInStudent = false;
int nstudent = 0;
while (fin.getline(str, LINE_LENGTH))
{
if (!strncmp(str, "teacher:", 8)){
bInTeacher = true;
bInStudent = false;
continue;
}
else if (!strncmp(str, "student:", 8)){
bInTeacher = false;
bInStudent = true;
continue;
}
else if (strlen(str) < 20){
continue;//assume the file name > 20
}
else if (bInTeacher){
readfile(str);
get_outinfo_file_name(str);
merged_info1.push_back(out_info_file);
process_record_file_to_ts();
}
else if (bInStudent){
readfile(str);
get_outinfo_file_name(str);
merged_info2.push_back(out_info_file);
process_record_file_to_ts();
}
}
return 0;
}
//#define TEST
int main(int argc, char * argv[])
{
if (argc < 3) {
printf(" merge_pip 1.0.1\n");
#ifdef TEST
const char * video = "D:\\media\\talk\\20181112\\talk915_824250397_105638\\137786519_20181112105817677.ts";
const char * dest = "D:\\media\\talk\\20181112\\talk915_824250397_105638\\137786519_20181112105817677.ts.jpg";
get_config_path();
load_codec_param();
init_merge_av();
get_video_last_frame_jpeg(video, dest);
merge_pic_silence(dest, 1.56, "D:\\media\\talk\\20181112\\talk915_824250397_105638\\137786519_20181112105817677_last_s156.ts");
#endif
if (argc < 2) {
printf(" merge_pip 1.0.2\n");
printf(" run ffmpeg to merge video files to one pip video according to record info file,\nusage:");
printf("\n %s record_info_filename1 record_filename2 [-p] [-k]", argv[0]);
printf("\n %s record_info_filename [-p] [-k]", argv[0]);
printf("\n -p :only print the command,don't run ffmpeg");
printf("\n -k :keep the temp files\n");
printf("\n -d :individual files for different time segment\n");
return -1;
}
... ... @@ -1573,7 +1717,7 @@ int main(int argc, char * argv[])
bool bmerge_files = true;
for (int i = 3; i < argc; i++){
for (int i = 2; i < argc; i++){
if (!strcmp(argv[i], "-p")){
only_print = true;
}
... ... @@ -1583,11 +1727,14 @@ int main(int argc, char * argv[])
else if (!strcmp(argv[i], "-n")){
bmerge_files = false;
}
else if (!strcmp(argv[i], "-d")){
out_one_video = false;
}
}
char merged_info1[1024];
char merged_info2[1024];
vector<string> merged_info1;
vector<string> merged_info2;
#if 0
if (bmerge_files) {
if (readfile(argv[1]) < 0) {
printf("open file: %s error", argv[1]);
... ... @@ -1613,27 +1760,38 @@ int main(int argc, char * argv[])
strcpy(merged_info1, argv[1]);
strcpy(merged_info2, argv[2]);
}
#else
process_record_info_to_ts(argv[1], merged_info1, merged_info2);
#endif
media_files.clear();
if (readfile(merged_info1, 0) < 0) {
printf("open file: %s error", merged_info1);
return -2;
for (int i = 0; i < merged_info1.size(); i++) {
if (readfile(merged_info1[i].c_str(), 0) < 0) {
printf("open file: %s error", merged_info1[i].c_str());
return -2;
}
}
if (readfile(merged_info2, 1) < 0) {
printf("open file: %s error", merged_info2);
return -2;
for (int i = 0; i < merged_info2.size(); i++) {
if (readfile(merged_info2[i].c_str(), 1) < 0) {
printf("open file: %s error", merged_info2[i].c_str());
return -2;
}
}
#if 0
get_outinfo_file_name(argv[1], argv[2]);
#else
get_outinfo_file_name(argv[1]);
#endif
process_merged_files_to_pip_files();
if (!keep_tmp_files && bmerge_files) {
removefiles(all_input_files_for_pip);
remove_file(merged_info1);
remove_file(merged_info2);
removefiles(merged_info1);
removefiles(merged_info2);
}
return 0;
... ...