Linux ffmpeg视频截图,C中操作JSON数据
ffmpeg 视频截图
上一篇介绍了ffmpeg 的安装, 这里介绍一下如何利用ffmpeg来创建视频缩略图。
ffmpeg参数较多,这里仅仅使用其中的几个,来完成创建视频截图的目的。
ffmpeg -ss 00:00:10 -i sample.mp4 -y -f image2 -t 0.001 -s 300x170 sample_out.jpg
参数 | 含义 |
---|---|
-ss | 指定ffmpeg的搜索时间点 |
-i | 指定输入的文件 |
-y | 覆盖输出 |
-f | 指定采用的格式 |
-t | 设置记录的时间 |
-s | 设置帧大小 |
需要注意的是-ss参数,把它放在-i之前,命令执行的时间更快些,这个很多网上的资料都有介绍:如果放在后面的话,ffmpeg会先读入视频然后逐步搜索到指定的时间,故花费时间较久,而-ss放在前面时,ffmpeg则会直接跳到指定时间。
如果要在C程序中执行这条命令,可以考虑使用execvp()函数, 或者popen和system函数。
下面的代码片段使用了execvp来执行该命令(留意execvp的参数),
char command[BUFSIZ] = "ffmpeg -ss 00:00:10 -i sample.mp4 -y -f image2 -t 0.001 -s 300x170 sample_out.jpg";
//to cut the cwd by " "
char delims[] = " ";
int argc = 1;
int i = 1;
char **argvtmp;
strcpy(argv[0],strtok(command,delims));
while(p = strtok(NULL,delims)){
strcpy(argv[i++],p);
argc++;
}//while
argvtmp = malloc(sizeof(char *)*argc+1);
int j;
for(j = 0;j < argc + 1;j++){
argvtmp[j] = malloc(sizeof(char)*100);
if(j < argc)
strcpy(argvtmp[j],argv[j]);
}//for
argvtmp[argc] = NULL;
if(execvp(argvtmp[0],argvtmp) < 0){
#ifdef DEBUG
printf("create video thumb failed!\n");
#endif
}
在C中操作JSON数据
这部分似乎和上一部分完全没关系,主要是因为自己项目的需要:使用json来传输视频的一些信息,其中包含视频的缩略图,因此就把这两部分放到一篇博客啦。
JSON是一种数据交换格式,全称是JavaScript Object Notation。这种格式中,要表示的东西被当做对象,对象由键值对(“item”:”value”)来表示,许多的对象可以构成一个数组。
{
"status": 1,
"data": [{
"name": "dubai.mp4",
"duration": "00:01:20.60",
"createTime": "2017-5-9 13:34",
}, {
"name": "360test.mp4",
"duration": "00:00:42.63",
"createTime": "2017-5-9 14:1",
}, {
"name": "panda.mp4",
"duration": "00:01:56.82",
"createTime": "2017-5-9 14:1",
}],
"msg": "SUCCESS"
}
比如上面这段JSON数据中,有一个”data”数组([]括起来的部分),其中有三个对象({}括起来的部分),每个对象有三个键值对。
要想在C中操作JSON数据,需要使用到cJSON,不过一般我们只需要两个文件即可cJSON.c 和cJSON.h。
可以在这里找到简单的使用介绍JSON的简单介绍以及C语言的JSON库使用
以本项目的为例,
char *video_json;
FILE *fp_json = fopen(video_list_json_path,"r+");
//video_list_json_path为原有JSON文件的位置
if(fp_json == NULL){
printf("open json file failed!\n");
}
fseek(fp_json,0,SEEK_END);
int fp_json_length = ftell(fp_json);
#ifdef DEBUG
printf("===length %d\n",fp_json_length);
#endif
video_json = (char*)malloc((fp_json_length+1) * sizeof(char));
fseek(fp_json,0,SEEK_SET);
fread(video_json,fp_json_length,sizeof(char),fp_json);
video_json[fp_json_length] = '\0';
cJSON *json = cJSON_Parse(video_json);
cJSON *array = NULL;
array = cJSON_GetObjectItem(json,"data");
cJSON *obj = NULL;
cJSON_AddItemToArray(array,obj = cJSON_CreateObject());
cJSON_AddStringToObject(obj,"name",video_info.video_name);
//video_info为视频信息的结构体,下同
cJSON_AddStringToObject(obj,"videoThumb",video_info.video_thumb_url);
cJSON_AddStringToObject(obj,"duration",video_info.video_duration);
cJSON_AddStringToObject(obj,"createTime",video_info.video_update_time);
cJSON_AddStringToObject(obj,"path",video_info.video_url);
FILE *fp_json_new = fopen(video_list_json_path_tmp,"w");
char *tmp_buf = cJSON_Print(json);
fwrite(tmp_buf,strlen(tmp_buf),1,fp_json_new);
//clean
cJSON_Delete(json);
fclose(fp_json);
fclose(fp_json_new);
remove(video_list_json_path);
rename(video_list_json_path_tmp,video_list_json_path);
其中关键的函数为:
函数原型 | 含义 |
---|---|
cJSON *cJSON_Parse(const char *value) | 解析JSON数据并返回cJSON结构 |
cJSON *cJSON_GetObjectItem(cJSON *object,const char *string) | 获取JSON对象 |
void cJSON_AddItemToArray(cJSON *array, cJSON *item) | 向数组中添加对象 |
cJSON_AddStringToObject(object,name,s) | (宏函数)向对象中添加字符串作为键值 |
上面的代码片段的目的为:读取现有的JSON文件,向其中添加一个视频信息对象,达到更新JSON文件的目的。因为JSON文件是文本文件,有很清晰易读的组织结构,我们也可以自己去完成读取解析等工作,不过可能健壮性并没有cJSON写的这么好,所以,如果有需要的话,直接使用就好了。在其他的语言如JS,Python中,对JSON的支持会更友好一些,这里只是因为项目的需要而使用了C。
结果
将上述两部结合起来:创建的缩略图可以通过地址来访问,所以我们的JSON文件中需要有类似”video_capture”:”/picture/pitcture1.jpg”的键值对,用来保存每个视频的缩略图地址。
因项目还没结题,就不贴完整代码出来了。仅仅介绍一下整个的思路。编译时,一个可能的Makefile为:
#updateJson
CC = gcc
SRC1 = updateJson.c
SRC2 = cJSON.c
.PHONY : clean
all:
$(CC) -g $(SRC1) $(SRC2) -o updateJson -lm
clean:
-rm cJSON.o updateJson.o updateJson
一并编译cJSON.c,这个c文件需要链接数学库。
执行的结果如下:
Reference:
ffmpeg参数中文详细解释
JSON的简单介绍以及C语言的JSON库使用
ffmpeg命令截图范例参考
cJSON