// // Created by 阳坤 on 2022/3/1. // #include "utils/video_similarity.h" #include "utils/count_down_latch.h" #include "ffmpeg/av_tools.h" extern "C" { #include "utils/md5.h" } typedef struct VsimBean { const char *filepath; const char *image_md5; std::vector lists; pthread_t id; } VsimBean; static void run(const char *filepath, std::vector *list) { long id = video_similarity_detection_init(filepath, nullptr); if (id > 0) { int ret = video_similarity_detection_start(id, 0, AUDIO, list); // char md5_str[64] = {0}; // if (get_file_md5(vsimBean->filepath, md5_str) > 0); // vsimBean->image_md5 = strdup(md5_str); video_similarity_detection_close(id); } } static void *run_thread(void *p) { auto *vsimBean = (VsimBean *) p; run(vsimBean->filepath, &vsimBean->lists); return 0; } static int *list_sim_compare(std::vector a, std::vector b) { int minFrames = MIN(a.size(), b.size()); int maxFrames = MAX(a.size(), b.size()); int sim_frame_count = 0; int arr[2]; //比较帧指纹 for (int k = 0; k < minFrames; ++k) { float v_sim = fingerprint_compare(a[k]->image_hash, b[k]->image_hash, minFrames); if (v_sim > 0.90) { sim_frame_count++; } } arr[0] = sim_frame_count; arr[1] = maxFrames; return arr; } typedef struct Test { const char *input; CountDownLatch *countDownLatch; }; static void *run(void *p) { auto *test = (Test *) p; const char *ret_json = get_video_similarity_list(test->input); printf("ret_json=%s\n", ret_json); test->countDownLatch->countDown(); free(test); pthread_exit(NULL); } /** * 1、判断比对文件的 MD5 是否相等 * 1.1、如果相等, * 1.1.1、判断媒体数据 mate 信息是否一致,如果一致,判断前面 N 关键帧的指纹码 * 1.2、如果不等 * 1.2.1、判断媒体数据 mate 信息是否一致, 如果一致,判断前面 N 关键帧的指纹码 * @param argc * @param argv * @return */ int main(int argc, char *argv[]) { int threads = 1; const char *inputs[1]; // inputs[0] = "{\"videoPath\":\"http://rescdn.yishihui.com/longvideo/transcode/video/b46fd76f98364b3abad8c1297a868f82-1526976612340.m3u8\",\"clips\":[{\"startTimeMs\":3000,\"endTimeMs\":4000},{\"startTimeMs\":6000,\"endTimeMs\":7000},{\"startTimeMs\":9000,\"endTimeMs\":10000},{\"startTimeMs\":12000,\"endTimeMs\":13000},{\"startTimeMs\":15000,\"endTimeMs\":16000},{\"startTimeMs\":18000,\"endTimeMs\":19000},{\"startTimeMs\":21000,\"endTimeMs\":22000},{\"startTimeMs\":24000,\"endTimeMs\":25000}]}"; inputs[0] = "{\"videoPath\":\"http://rescdn.yishihui.com/longvideo/transcode/video/e6b5cfa854b24e3f87d133e3b2da0ade1530635451140-randomKgqMSnitde.mp4\",\"clips\":[{\"startTimeMs\":14000,\"endTimeMs\":15000},{\"startTimeMs\":28000,\"endTimeMs\":29000},{\"startTimeMs\":42000,\"endTimeMs\":43000},{\"startTimeMs\":56000,\"endTimeMs\":57000},{\"startTimeMs\":70000,\"endTimeMs\":71000},{\"startTimeMs\":84000,\"endTimeMs\":85000},{\"startTimeMs\":98000,\"endTimeMs\":99000},{\"startTimeMs\":112000,\"endTimeMs\":113000}]}"; // inputs[2] = "{\"videoPath\":\"http://rescdn.yishihui.com/longvideo/transcode/video/3dbf36e8ec27479581514b8b7b4c8034-1526924772832-safe1594892815.m3u8\",\"clips\":[{\"startTimeMs\":6000,\"endTimeMs\":7000},{\"startTimeMs\":12000,\"endTimeMs\":13000},{\"startTimeMs\":18000,\"endTimeMs\":19000},{\"startTimeMs\":24000,\"endTimeMs\":25000},{\"startTimeMs\":30000,\"endTimeMs\":31000},{\"startTimeMs\":36000,\"endTimeMs\":37000},{\"startTimeMs\":42000,\"endTimeMs\":43000},{\"startTimeMs\":48000,\"endTimeMs\":49000}]}"; // inputs[3] = "{\"videoPath\":\"http://rescdn.yishihui.com/longvideo/transcode/video/3dbf36e8ec27479581514b8b7b4c8034-1526924772832-safe1594892815.m3u8\",\"clips\":[{\"startTimeMs\":6000,\"endTimeMs\":7000},{\"startTimeMs\":12000,\"endTimeMs\":13000},{\"startTimeMs\":18000,\"endTimeMs\":19000},{\"startTimeMs\":24000,\"endTimeMs\":25000},{\"startTimeMs\":30000,\"endTimeMs\":31000},{\"startTimeMs\":36000,\"endTimeMs\":37000},{\"startTimeMs\":42000,\"endTimeMs\":43000},{\"startTimeMs\":48000,\"endTimeMs\":49000}]}"; // for (;;) { CountDownLatch *countDownLatch = new CountDownLatch(threads); for (int i = 0; i < threads; ++i) { Test *test = static_cast(malloc(sizeof(Test))); test->countDownLatch = countDownLatch; test->input = inputs[i]; pthread_t id; pthread_create(&id,0,run,test); } countDownLatch->await(); delete countDownLatch; // } return 1; // const char *out_json = "{\n" // " \"videoPath\": \"\\\"/root/data/xxx.mp4\\\"\",\n" // " \"clips\": [\n" // " {\n" // " \"startTimeMs\": 15000,\n" // " \"endTimeMs\": 25000,\n" // " \"fingerprintCode\": [\n" // " \"\\\"0001000100101010101010\\\"\",\n" // " \"\\\"0001000100101010101010\\\"\",\n" // " \"\\\"0001000100101010101010\\\"\",\n" // " \"\\\"0001000100101010101010\\\"\"\n" // " ]\n" // " }\n" // " ]\n" // "}"; // auto vs = json2VideoSimilarity(input_json); // auto json = videoSimilarity2json(vs); int32_t size = 7; const char *filepath[size]; //票圈视频iOS客户端上传 filepath[0] = "http://rescdn.yishihui.com/longvideo/video/vpc/20220309/17025689Igao51Q0IMBYw8aNKH"; //ios 原生上传 filepath[1] = "http://rescdn.yishihui.com/longvideo/video/vpc/20220309/17025689VvI5KURrrxzlZ0Kcdv"; //iOS h5上传 filepath[2] = "http://rescdn.yishihui.com/longvideo/video/vpc/20220309/17025689iBy9WFswYdBNblY9au"; //票圈视频安卓客户端上传 filepath[3] = "http://rescdn.yishihui.com/longvideo/video/vpc/20220309/17677590exDXG6q75ELejK7aMY"; //安卓h5上传 filepath[4] = "http://rescdn.yishihui.com/longvideo/video/vpc/20220309/176775906GoWtUCYoVZYDbO1XX"; //安卓原生上传 filepath[5] = ""; //PC 上传 // filepath[5] = "http://rescdn.yishihui.com/longvideo/video/vpc/20220309/17025689nSyGzifJFr4Apl0zc8"; filepath[5] = "http://rescdn.yishihui.com/longvideo/video/vpc/20220310/701939000F0qpyCLetflI3COz"; http://rescdn.yishihui.com/longvideo/video/vpc/20220304/17938576TxEh0UJXpzcoYRJuHu //本地 local 上传的视频 filepath[6] = "/Users/devyk/Data/Project/sample/github_code/OpenCVSample/temp/19581045gIiFKepxbbplF3XtsG.mp4"; // run(vs->videoPath,&vs->clips); // const char * ret = videoSimilarity2json(vs); // const char *local_url = "/Users/devyk/Data/Project/sample/github_code/OpenCVSample/temp/19581045gIiFKepxbbplF3XtsG.mp4"; // std::vector local_list; // run(local_url, &local_list); std::vector lists[size]; int split_count = 10; // int total = 3960000; int ii = 1000 * 60 * 6; int start = ii; for (int i = 0; i < size; ++i) { auto start_time = getCurrentTimeMills(); start = ii; for (int j = 0; j < split_count; ++j) { if (j == 0 || j == split_count - 1) { continue; } auto *item = new VideoSimilarityModel(); item->startTimeMs = start; item->endTimeMs = item->startTimeMs + 1000; lists[i].push_back(item); start += ii; } LOGE(">>>filepath=%s \n", filepath[i]); run(filepath[i], &lists[i]); LOGE("<< local = lists[size - 1]; //相似 hash 值 int test_vis[6][8] = {0}; //所有的 帧 int test_vis_total[6][8] = {0}; for (int j = 0; j < size - 1; ++j) { for (int g = 0; g < lists[j].size(); ++g) { int *cur_sim = list_sim_compare(local[g]->hashs, lists[j][g]->hashs); int a = cur_sim[0]; int b = cur_sim[1]; test_vis[j][g] = a; test_vis_total[j][g] = b; } } for (int i = 0; i < size - 1; ++i) { int a_t = 0, b_t = 0; for (int j = 0; j < 8; ++j) { a_t += test_vis[i][j]; b_t += test_vis_total[i][j]; } LOGE("%s %s 相似度 = %f \n", filepath[6], filepath[i], a_t * 1.0 / b_t * 1.0); } printf(""); LOGE("end \n"); return 0; }