- 论坛徽章:
- 2
|
本帖最后由 lhd666 于 2017-10-22 00:56 编辑
本来想把 ffmpeg 命令行简单封装一下,让它易于使用,但是我实在是太菜,反而弄得更啰嗦难用了,大家指导一下,指点思路呗
- #include <glib.h>
- struct ffmpeg_wrap {
- char *input_url;
- char *output_url;
- GVariantDict *input_dict;
- GVariantDict *output_dict;
- gboolean overwrite;
- };
- struct ffmpeg_wrap *ffmpeg_wrap_new(void)
- {
- struct ffmpeg_wrap *wrap;
- wrap = g_new0(struct ffmpeg_wrap, 1);
- wrap->input_dict = g_variant_dict_new(NULL);
- wrap->output_dict = g_variant_dict_new(NULL);
- wrap->overwrite = FALSE;
- return wrap;
- }
- void ffmpeg_wrap_free(struct ffmpeg_wrap *wrap)
- {
- g_free(wrap->input_url);
- g_free(wrap->output_url);
- g_variant_dict_unref(wrap->input_dict);
- g_variant_dict_unref(wrap->output_dict);
- g_free(wrap);
- }
- void ffmpeg_wrap_input_set_url(struct ffmpeg_wrap *wrap, const gchar *url)
- {
- if (wrap->input_url)
- g_free(wrap->input_url);
- wrap->input_url = g_strdup(url);
- }
- void ffmpeg_wrap_output_set_url(struct ffmpeg_wrap *wrap, const gchar *url)
- {
- if (wrap->output_url)
- g_free(wrap->output_url);
- wrap->output_url = g_strdup(url);
- }
- /*
- * 设置输出视频分辨率,默认使用源视频分辨率
- * 如:1280, 720
- */
- void ffmpeg_wrap_output_set_size(struct ffmpeg_wrap *wrap, guint width, guint height)
- {
- g_variant_dict_insert(wrap->output_dict, "-s", "(uu)", width, height);
- }
- /*
- * 设置输出音频编码格式,不设置ffmpeg会根据输出文件名自动推导,设置为"copy",
- * 可以直接复制音频,避免解码和编码,但如果输出文件容器不支持,执行会失败
- * 如:"aac"
- */
- void ffmpeg_wrap_output_set_acodec(struct ffmpeg_wrap *wrap, const gchar *acodec)
- {
- g_variant_dict_insert(wrap->output_dict, "-acodec", "s", acodec);
- }
- /*
- * 设置输出音频编码器格式,不设置ffmpeg会根据输出文件名自动推导,设置为"copy",
- * 可以直接复制视频,避免解码和编码,但如果输出文件容器不支持,执行会失败
- * 如:"h264"
- */
- void ffmpeg_wrap_output_set_vcodec(struct ffmpeg_wrap *wrap, const gchar *vcodec)
- {
- g_variant_dict_insert(wrap->output_dict, "-vcodec", "s", vcodec);
- }
- /*
- * 设置输出帧率,默认25
- */
- void ffmpeg_wrap_output_set_fps(struct ffmpeg_wrap *wrap, guint fps)
- {
- g_variant_dict_insert(wrap->output_dict, "-r", "u", fps);
- }
- /*
- * 设置最大输出码率,单位:kbps
- */
- void ffmpeg_wrap_output_set_maxrate(struct ffmpeg_wrap *wrap, guint maxrate)
- {
- g_variant_dict_insert(wrap->output_dict, "-maxrate", "u", maxrate);
- }
- /*
- * 设置最小输出码率,单位:kbps
- */
- void ffmpeg_wrap_output_set_minrate(struct ffmpeg_wrap *wrap, guint minrate)
- {
- g_variant_dict_insert(wrap->output_dict, "-minrate", "u", minrate);
- }
- /*
- * 不输出音频
- */
- void ffmpeg_wrap_output_disable_audio(struct ffmpeg_wrap *wrap)
- {
- g_variant_dict_insert(wrap->output_dict, "-an", "s", "");
- }
- /*
- * 不输出视频
- */
- void ffmpeg_wrap_output_disable_video(struct ffmpeg_wrap *wrap)
- {
- g_variant_dict_insert(wrap->output_dict, "-vn", "s", "");
- }
- /*
- * 如果输出文件名重复,覆盖
- */
- void ffmpeg_wrap_output_set_overwrite(struct ffmpeg_wrap *wrap)
- {
- wrap->overwrite = TRUE;
- }
- static GString *get_kwargs(GString *comand, GVariantDict *dict)
- {
- GVariantIter iter;
- GVariant *value;
- gchar *key;
- g_variant_iter_init(&iter, g_variant_dict_end(dict));
- while (g_variant_iter_loop(&iter, "{sv}", &key, &value)) {
- if (g_variant_is_of_type(value, G_VARIANT_TYPE_STRING)) {
- g_string_append_printf(comand, "%s %s ", key, g_variant_get_string(value, NULL));
- } else if (g_variant_is_of_type(value, G_VARIANT_TYPE_UINT32)) {
- g_string_append_printf(comand, "%s %u ", key, g_variant_get_uint32(value));
- } else if (g_variant_is_of_type(value, G_VARIANT_TYPE_TUPLE)) {
- /* FIXME: 目前tuple只能分辨率,但也许这样做并不安全 */
- guint32 width, height;
- g_variant_get(value, "(uu)", &width, &height);
- g_string_append_printf(comand, "%s %ux%u ", key, width, height);
- }
- }
- return comand;
- }
- static GString *get_command(struct ffmpeg_wrap *wrap)
- {
- GString *comand;
- comand = g_string_new("/bin/ffmpeg ");
- /* 输入参数,好吧,实际上并没有设置(<: */
- get_kwargs(comand, wrap->input_dict);
- g_string_append_printf(comand, "-i %s ", wrap->input_url);
- /* 输出参数 */
- get_kwargs(comand, wrap->output_dict);
- g_string_append(comand, wrap->output_url);
- /* 重名时是否覆盖输出文件 */
- if (wrap->overwrite)
- g_string_append(comand, " -y");
- return comand;
- }
- void ffmpeg_wrap_run(struct ffmpeg_wrap *wrap)
- {
- GString *comand;
- comand = get_command(wrap);
- /* 需要增加system()或popen() */
- g_print("%s\n", comand->str);
- g_string_free(comand, TRUE);
- }
- int main(int argc, char **argv)
- {
- struct ffmpeg_wrap *wrap;
- wrap = ffmpeg_wrap_new();
- ffmpeg_wrap_input_set_url(wrap, "input.mp4");
- ffmpeg_wrap_output_set_url(wrap, "output.mp4");
- ffmpeg_wrap_output_set_fps(wrap, 25);
- ffmpeg_wrap_output_set_vcodec(wrap, "h264");
- ffmpeg_wrap_output_set_acodec(wrap, "aac");
- ffmpeg_wrap_output_set_size(wrap, 1280, 720);
- ffmpeg_wrap_output_set_overwrite(wrap);
- ffmpeg_wrap_run(wrap);
- ffmpeg_wrap_free(wrap);
- return 0;
- }
复制代码
它会输出如下信息:
/bin/ffmpeg -i input.mp4 -vcodec h264 -acodec aac -r 25 -s 1280x720 output.mp4 -y
我想的是将参数分为输入和输出两块,用字典存储它们。如果参数后面有值,字典存储正好,如果没值,值用""代替,最后拼接成要执行的命令,但结果就是这个鸟样子了。
|
|