胡斌

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 @@ @@ -12,6 +12,7 @@
12 12
13 bool only_print = false; 13 bool only_print = false;
14 bool keep_tmp_files = false; 14 bool keep_tmp_files = false;
  15 +bool out_one_video = true;
15 using namespace std; 16 using namespace std;
16 17
17 enum media_type{ 18 enum media_type{
@@ -57,6 +58,7 @@ vector<fileinfo> media_files; @@ -57,6 +58,7 @@ vector<fileinfo> media_files;
57 const char * MERGED_PREFIX = ""; 58 const char * MERGED_PREFIX = "";
58 const char * PIP_PREFIX = "pip_"; 59 const char * PIP_PREFIX = "pip_";
59 60
  61 +float get_file_duration(const char *mediafile, bool bVideo);
60 62
61 void run_shell_cmd(const char * cmd) 63 void run_shell_cmd(const char * cmd)
62 { 64 {
@@ -241,6 +243,7 @@ void get_video_first_frame_jpeg(const char * video, const char * destfile) @@ -241,6 +243,7 @@ void get_video_first_frame_jpeg(const char * video, const char * destfile)
241 run_shell_cmd(buf); 243 run_shell_cmd(buf);
242 } 244 }
243 245
  246 +
244 void merge_audio_pic(const char * audio, const char * picfile, const char * destfile) 247 void merge_audio_pic(const char * audio, const char * picfile, const char * destfile)
245 { 248 {
246 char buf[2048]; 249 char buf[2048];
@@ -274,7 +277,7 @@ void merge_audio_video(const char * audio, const char * video, int rotate, const @@ -274,7 +277,7 @@ void merge_audio_video(const char * audio, const char * video, int rotate, const
274 void merge_video_pip(const char * ch0, const char * ch1, const char * destfile) 277 void merge_video_pip(const char * ch0, const char * ch1, const char * destfile)
275 { 278 {
276 char buf[2048]; 279 char buf[2048];
277 - sprintf(buf, "ffmpeg -i %s -i %s %s %s %s", ch0, ch1, pip_param, av_codec_param, destfile); 280 + sprintf(buf, "ffmpeg -y -i %s -i %s %s %s %s", ch0, ch1, pip_param, av_codec_param, destfile);
278 run_shell_cmd(buf); 281 run_shell_cmd(buf);
279 } 282 }
280 283
@@ -382,7 +385,6 @@ float parse_ffmpeg_duration(const char * file) @@ -382,7 +385,6 @@ float parse_ffmpeg_duration(const char * file)
382 385
383 if (hms.size() != 3) { 386 if (hms.size() != 3) {
384 printf("\nerro parsing duration in %s, the duration string is:%s\n", file, content); 387 printf("\nerro parsing duration in %s, the duration string is:%s\n", file, content);
385 - delete content;  
386 return -1.0; 388 return -1.0;
387 } 389 }
388 390
@@ -568,7 +570,92 @@ char silence_aac_file[1024]; @@ -568,7 +570,92 @@ char silence_aac_file[1024];
568 char out_info_file[1024]; 570 char out_info_file[1024];
569 FILE * fp_out_info = NULL; 571 FILE * fp_out_info = NULL;
570 572
  573 +void merge_pic_silence(const char * pic, float duration, const char * destfile)
  574 +{
  575 + char buf[2048];
  576 + 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);
  577 + run_shell_cmd(buf);
  578 +}
  579 +
  580 +int parse_ffmpeg_lastframe(const char * file)
  581 +{
  582 + FILE * fp = fopen(file, "rb");
  583 + if (!fp) {
  584 + printf("\nOpen %s error\n", file);
  585 + return -1.0;
  586 + }
  587 + fseek(fp, 0l, SEEK_END);
  588 + long file_len = ftell(fp);
  589 + fseek(fp, 0l, SEEK_SET);
  590 +
  591 + char * content = new char[file_len + 1];
  592 + fread(content, 1, file_len, fp);
  593 + fclose(fp);
  594 +
  595 + content[file_len] = 0;
  596 +
  597 + if (!keep_tmp_files) {
  598 + remove_file(file);
  599 + }
  600 +
  601 + char * pLastFrame = strstr(content, "frame=");
  602 + if (!pLastFrame){
  603 + printf("\ncan't find 'frame' in %s\n", file);
  604 + delete content;
  605 + return 0;
  606 + }
  607 + while (1){
  608 + char * pFrame = strstr(pLastFrame + 6, "frame=");
  609 + if (!pFrame){
  610 + break;
  611 + }
  612 + pLastFrame = pFrame;
  613 + }
  614 +
  615 + int frame = atoi(pLastFrame + 6);
571 616
  617 + delete content;
  618 + return frame;
  619 +}
  620 +
  621 +void get_video_last_frame_jpeg(const char * video, const char * destfile) {
  622 + char buf[2048];
  623 + //first ,get
  624 + float duration = get_file_duration(video, true);
  625 + if (duration > 0) {
  626 + float start = 0;
  627 + if (duration > 1) {
  628 + start = duration - 1;
  629 + }
  630 +#ifdef WIN32
  631 + sprintf(buf, "ffmpeg -y -i %s -ss %.1f -an %s_last_%%d.jpg > %s.txt 2>&1", video, start, video,video);
  632 +#else
  633 + sprintf(buf, "ffmpeg -y -i %s -ss %.1f -an %s_last_%%d.jpg &> %s.txt", video, start, video, video);
  634 +#endif
  635 + run_shell_cmd(buf);
  636 + sprintf(buf,"%s.txt", video);
  637 + int last_frame = parse_ffmpeg_lastframe(buf);
  638 + if (last_frame > 0) {
  639 +#ifdef WIN32
  640 + sprintf(buf, "copy %s_last_%d.jpg %s", video,last_frame,destfile);
  641 +#else
  642 + sprintf(buf, "cp %s_last_%d.jpg %s", video, last_frame,destfile);
  643 +#endif
  644 + run_shell_cmd(buf);
  645 + for (int i = 1; i <= last_frame; i++) {
  646 + sprintf(buf, "%s_last_%d.jpg", video, i);
  647 + tmp_files.push_back(buf);
  648 + }
  649 + }
  650 + }
  651 + else {
  652 +#ifdef WIN32
  653 + sprintf(buf, "copy %s %s", blank_pic_file, destfile);
  654 +#else
  655 + sprintf(buf, "cp %s %s", blank_pic_file, destfile);
  656 +#endif
  657 + }
  658 +}
572 659
573 void add_media_info(media_info m) 660 void add_media_info(media_info m)
574 { 661 {
@@ -1190,12 +1277,25 @@ int get_output_file_name(int i, const char * filename, const char * prefix,char @@ -1190,12 +1277,25 @@ int get_output_file_name(int i, const char * filename, const char * prefix,char
1190 return 0; 1277 return 0;
1191 } 1278 }
1192 1279
1193 -bool is_need_output(int nOutPutFile, vector<media_info> & cur_processing, const char * first_file, char * outputfile, const char * prefix="") 1280 +bool is_need_output(int & nOutPutFile, vector<media_info> & cur_processing, const char * first_file, char * outputfile, const char * prefix="")
1194 { 1281 {
1195 if (sorted_infos.size()) { 1282 if (sorted_infos.size()) {
1196 - int lastEnd = cur_processing[cur_processing.size() - 1].type_time;  
1197 - int nextStart = sorted_infos.front().type_time;  
1198 - if (nextStart - lastEnd < 0.2) { 1283 + float lastEnd = cur_processing[cur_processing.size() - 1].type_time;
  1284 + float nextStart = sorted_infos.front().type_time;
  1285 + float gap = nextStart - lastEnd;
  1286 + if ( gap < 0.2) {
  1287 + return false;
  1288 + }
  1289 + else if(out_one_video){
  1290 + string last_merged_video = merged_files[merged_files.size() - 1];
  1291 + char buf[1024];
  1292 + sprintf(buf, "%s_last_frame.jpg", last_merged_video.c_str());
  1293 + get_video_last_frame_jpeg(last_merged_video.c_str(), buf);
  1294 + char buf_dest[1024];
  1295 + sprintf(buf_dest, "%d.ts", nOutPutFile++);
  1296 + merge_pic_silence(buf, gap, buf_dest);
  1297 + merged_files.push_back(buf_dest);
  1298 + tmp_files.push_back(buf);
1199 return false; 1299 return false;
1200 } 1300 }
1201 } 1301 }
@@ -1380,7 +1480,7 @@ int process_merged_files_to_pip_files() @@ -1380,7 +1480,7 @@ int process_merged_files_to_pip_files()
1380 return 0; 1480 return 0;
1381 } 1481 }
1382 1482
1383 -int readfile(char * filename) 1483 +int readfile(const char * filename)
1384 { 1484 {
1385 init_read_file(); 1485 init_read_file();
1386 media_files.clear(); 1486 media_files.clear();
@@ -1454,7 +1554,7 @@ float get_start_time_from_filename(const char * filename) @@ -1454,7 +1554,7 @@ float get_start_time_from_filename(const char * filename)
1454 1554
1455 vector<string> all_input_files_for_pip; 1555 vector<string> all_input_files_for_pip;
1456 1556
1457 -int readfile(char * filename, int channel) 1557 +int readfile(const char * filename, int channel)
1458 { 1558 {
1459 init_read_file(); 1559 init_read_file();
1460 1560
@@ -1535,35 +1635,79 @@ void load_codec_param() @@ -1535,35 +1635,79 @@ void load_codec_param()
1535 } 1635 }
1536 } 1636 }
1537 1637
1538 -void get_outinfo_file_name(char * input1 , char * input2) 1638 +void get_outinfo_file_name(char * input)
1539 { 1639 {
1540 - strcpy(out_info_file, input1); 1640 + strcpy(out_info_file, input);
1541 char * p = strstr(out_info_file, "."); 1641 char * p = strstr(out_info_file, ".");
1542 if (p) { 1642 if (p) {
1543 *p = 0; 1643 *p = 0;
1544 } 1644 }
1545 - strcat(out_info_file, "__");  
1546 - strcat(out_info_file, input2); 1645 + strcat(out_info_file, "_out.txt");
1547 } 1646 }
1548 1647
1549 -void get_outinfo_file_name(char * input) 1648 +int process_record_info_to_ts(char * record_info, vector<string> & merged_info1, vector<string> & merged_info2)
1550 { 1649 {
1551 - strcpy(out_info_file, input);  
1552 - char * p = strstr(out_info_file, ".");  
1553 - if (p) {  
1554 - *p = 0; 1650 + ifstream fin(record_info);
  1651 + if (!fin) {
  1652 + return -1;
1555 } 1653 }
1556 - strcat(out_info_file, "_out.txt"); 1654 +
  1655 + const int LINE_LENGTH = 1000;
  1656 + char str[LINE_LENGTH];
  1657 + bool bInTeacher = false;
  1658 + bool bInStudent = false;
  1659 + int nstudent = 0;
  1660 + while (fin.getline(str, LINE_LENGTH))
  1661 + {
  1662 + if (!strncmp(str, "teacher:", 8)){
  1663 + bInTeacher = true;
  1664 + bInStudent = false;
  1665 + continue;
  1666 + }
  1667 + else if (!strncmp(str, "student:", 8)){
  1668 + bInTeacher = false;
  1669 + bInStudent = true;
  1670 + continue;
  1671 + }
  1672 + else if (strlen(str) < 20){
  1673 + continue;//assume the file name > 20
  1674 + }
  1675 + else if (bInTeacher){
  1676 + readfile(str);
  1677 + get_outinfo_file_name(str);
  1678 + merged_info1.push_back(out_info_file);
  1679 + process_record_file_to_ts();
  1680 + }
  1681 + else if (bInStudent){
  1682 + readfile(str);
  1683 + get_outinfo_file_name(str);
  1684 + merged_info2.push_back(out_info_file);
  1685 + process_record_file_to_ts();
  1686 + }
  1687 + }
  1688 + return 0;
1557 } 1689 }
1558 1690
  1691 +//#define TEST
1559 int main(int argc, char * argv[]) 1692 int main(int argc, char * argv[])
1560 { 1693 {
1561 - if (argc < 3) {  
1562 - printf(" merge_pip 1.0.1\n"); 1694 +#ifdef TEST
  1695 + const char * video = "D:\\media\\talk\\20181112\\talk915_824250397_105638\\137786519_20181112105817677.ts";
  1696 + const char * dest = "D:\\media\\talk\\20181112\\talk915_824250397_105638\\137786519_20181112105817677.ts.jpg";
  1697 + get_config_path();
  1698 + load_codec_param();
  1699 + init_merge_av();
  1700 + get_video_last_frame_jpeg(video, dest);
  1701 + merge_pic_silence(dest, 1.56, "D:\\media\\talk\\20181112\\talk915_824250397_105638\\137786519_20181112105817677_last_s156.ts");
  1702 +#endif
  1703 +
  1704 + if (argc < 2) {
  1705 + printf(" merge_pip 1.0.2\n");
1563 printf(" run ffmpeg to merge video files to one pip video according to record info file,\nusage:"); 1706 printf(" run ffmpeg to merge video files to one pip video according to record info file,\nusage:");
1564 - printf("\n %s record_info_filename1 record_filename2 [-p] [-k]", argv[0]); 1707 + printf("\n %s record_info_filename [-p] [-k]", argv[0]);
1565 printf("\n -p :only print the command,don't run ffmpeg"); 1708 printf("\n -p :only print the command,don't run ffmpeg");
1566 printf("\n -k :keep the temp files\n"); 1709 printf("\n -k :keep the temp files\n");
  1710 + printf("\n -d :individual files for different time segment\n");
1567 return -1; 1711 return -1;
1568 } 1712 }
1569 1713
@@ -1573,7 +1717,7 @@ int main(int argc, char * argv[]) @@ -1573,7 +1717,7 @@ int main(int argc, char * argv[])
1573 1717
1574 bool bmerge_files = true; 1718 bool bmerge_files = true;
1575 1719
1576 - for (int i = 3; i < argc; i++){ 1720 + for (int i = 2; i < argc; i++){
1577 if (!strcmp(argv[i], "-p")){ 1721 if (!strcmp(argv[i], "-p")){
1578 only_print = true; 1722 only_print = true;
1579 } 1723 }
@@ -1583,11 +1727,14 @@ int main(int argc, char * argv[]) @@ -1583,11 +1727,14 @@ int main(int argc, char * argv[])
1583 else if (!strcmp(argv[i], "-n")){ 1727 else if (!strcmp(argv[i], "-n")){
1584 bmerge_files = false; 1728 bmerge_files = false;
1585 } 1729 }
  1730 + else if (!strcmp(argv[i], "-d")){
  1731 + out_one_video = false;
  1732 + }
1586 } 1733 }
1587 1734
1588 - char merged_info1[1024];  
1589 - char merged_info2[1024];  
1590 - 1735 + vector<string> merged_info1;
  1736 + vector<string> merged_info2;
  1737 +#if 0
1591 if (bmerge_files) { 1738 if (bmerge_files) {
1592 if (readfile(argv[1]) < 0) { 1739 if (readfile(argv[1]) < 0) {
1593 printf("open file: %s error", argv[1]); 1740 printf("open file: %s error", argv[1]);
@@ -1613,27 +1760,38 @@ int main(int argc, char * argv[]) @@ -1613,27 +1760,38 @@ int main(int argc, char * argv[])
1613 strcpy(merged_info1, argv[1]); 1760 strcpy(merged_info1, argv[1]);
1614 strcpy(merged_info2, argv[2]); 1761 strcpy(merged_info2, argv[2]);
1615 } 1762 }
  1763 +#else
  1764 + process_record_info_to_ts(argv[1], merged_info1, merged_info2);
1616 1765
  1766 +#endif
1617 1767
1618 media_files.clear(); 1768 media_files.clear();
1619 - if (readfile(merged_info1, 0) < 0) {  
1620 - printf("open file: %s error", merged_info1);  
1621 - return -2; 1769 + for (int i = 0; i < merged_info1.size(); i++) {
  1770 + if (readfile(merged_info1[i].c_str(), 0) < 0) {
  1771 + printf("open file: %s error", merged_info1[i].c_str());
  1772 + return -2;
  1773 + }
1622 } 1774 }
1623 1775
1624 - if (readfile(merged_info2, 1) < 0) {  
1625 - printf("open file: %s error", merged_info2);  
1626 - return -2; 1776 + for (int i = 0; i < merged_info2.size(); i++) {
  1777 + if (readfile(merged_info2[i].c_str(), 1) < 0) {
  1778 + printf("open file: %s error", merged_info2[i].c_str());
  1779 + return -2;
  1780 + }
1627 } 1781 }
1628 1782
  1783 +#if 0
1629 get_outinfo_file_name(argv[1], argv[2]); 1784 get_outinfo_file_name(argv[1], argv[2]);
  1785 +#else
  1786 + get_outinfo_file_name(argv[1]);
  1787 +#endif
1630 1788
1631 process_merged_files_to_pip_files(); 1789 process_merged_files_to_pip_files();
1632 1790
1633 if (!keep_tmp_files && bmerge_files) { 1791 if (!keep_tmp_files && bmerge_files) {
1634 removefiles(all_input_files_for_pip); 1792 removefiles(all_input_files_for_pip);
1635 - remove_file(merged_info1);  
1636 - remove_file(merged_info2); 1793 + removefiles(merged_info1);
  1794 + removefiles(merged_info2);
1637 } 1795 }
1638 1796
1639 return 0; 1797 return 0;