免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2711 | 回复: 0
打印 上一主题 下一主题

[C] ffmpeg命令行封装 [复制链接]

论坛徽章:
2
15-16赛季CBA联赛之天津
日期:2016-12-20 17:56:18CU十四周年纪念徽章
日期:2017-04-20 16:30:16
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2017-10-22 00:51 |只看该作者 |倒序浏览
本帖最后由 lhd666 于 2017-10-22 00:56 编辑

本来想把 ffmpeg 命令行简单封装一下,让它易于使用,但是我实在是太菜,反而弄得更啰嗦难用了,大家指导一下,指点思路呗
  1. #include <glib.h>

  2. struct ffmpeg_wrap {
  3.         char *input_url;
  4.         char *output_url;
  5.         GVariantDict *input_dict;
  6.         GVariantDict *output_dict;
  7.         gboolean overwrite;
  8. };


  9. struct ffmpeg_wrap *ffmpeg_wrap_new(void)
  10. {
  11.         struct ffmpeg_wrap *wrap;

  12.         wrap = g_new0(struct ffmpeg_wrap, 1);
  13.         wrap->input_dict = g_variant_dict_new(NULL);
  14.         wrap->output_dict = g_variant_dict_new(NULL);
  15.         wrap->overwrite = FALSE;

  16.         return wrap;
  17. }

  18. void ffmpeg_wrap_free(struct ffmpeg_wrap *wrap)
  19. {
  20.         g_free(wrap->input_url);
  21.         g_free(wrap->output_url);
  22.         g_variant_dict_unref(wrap->input_dict);
  23.         g_variant_dict_unref(wrap->output_dict);
  24.         g_free(wrap);
  25. }

  26. void ffmpeg_wrap_input_set_url(struct ffmpeg_wrap *wrap, const gchar *url)
  27. {
  28.         if (wrap->input_url)
  29.                 g_free(wrap->input_url);
  30.         wrap->input_url = g_strdup(url);
  31. }

  32. void ffmpeg_wrap_output_set_url(struct ffmpeg_wrap *wrap, const gchar *url)
  33. {
  34.         if (wrap->output_url)
  35.                 g_free(wrap->output_url);
  36.         wrap->output_url = g_strdup(url);
  37. }

  38. /*
  39. * 设置输出视频分辨率,默认使用源视频分辨率
  40. * 如:1280, 720
  41. */
  42. void ffmpeg_wrap_output_set_size(struct ffmpeg_wrap *wrap, guint width, guint height)
  43. {
  44.         g_variant_dict_insert(wrap->output_dict, "-s", "(uu)", width, height);
  45. }

  46. /*
  47. * 设置输出音频编码格式,不设置ffmpeg会根据输出文件名自动推导,设置为"copy",
  48. * 可以直接复制音频,避免解码和编码,但如果输出文件容器不支持,执行会失败
  49. * 如:"aac"
  50. */
  51. void ffmpeg_wrap_output_set_acodec(struct ffmpeg_wrap *wrap, const gchar *acodec)
  52. {
  53.         g_variant_dict_insert(wrap->output_dict, "-acodec", "s", acodec);
  54. }

  55. /*
  56. * 设置输出音频编码器格式,不设置ffmpeg会根据输出文件名自动推导,设置为"copy",
  57. * 可以直接复制视频,避免解码和编码,但如果输出文件容器不支持,执行会失败
  58. * 如:"h264"
  59. */
  60. void ffmpeg_wrap_output_set_vcodec(struct ffmpeg_wrap *wrap, const gchar *vcodec)
  61. {
  62.         g_variant_dict_insert(wrap->output_dict, "-vcodec", "s", vcodec);
  63. }

  64. /*
  65. * 设置输出帧率,默认25
  66. */
  67. void ffmpeg_wrap_output_set_fps(struct ffmpeg_wrap *wrap, guint fps)
  68. {
  69.         g_variant_dict_insert(wrap->output_dict, "-r", "u", fps);
  70. }

  71. /*
  72. * 设置最大输出码率,单位:kbps
  73. */
  74. void ffmpeg_wrap_output_set_maxrate(struct ffmpeg_wrap *wrap, guint maxrate)
  75. {
  76.         g_variant_dict_insert(wrap->output_dict, "-maxrate", "u", maxrate);
  77. }

  78. /*
  79. * 设置最小输出码率,单位:kbps
  80. */
  81. void ffmpeg_wrap_output_set_minrate(struct ffmpeg_wrap *wrap, guint minrate)
  82. {
  83.         g_variant_dict_insert(wrap->output_dict, "-minrate", "u", minrate);
  84. }

  85. /*
  86. * 不输出音频
  87. */
  88. void ffmpeg_wrap_output_disable_audio(struct ffmpeg_wrap *wrap)
  89. {
  90.         g_variant_dict_insert(wrap->output_dict, "-an", "s", "");
  91. }

  92. /*
  93. * 不输出视频
  94. */
  95. void ffmpeg_wrap_output_disable_video(struct ffmpeg_wrap *wrap)
  96. {
  97.         g_variant_dict_insert(wrap->output_dict, "-vn", "s", "");
  98. }

  99. /*
  100. * 如果输出文件名重复,覆盖
  101. */
  102. void ffmpeg_wrap_output_set_overwrite(struct ffmpeg_wrap *wrap)
  103. {
  104.         wrap->overwrite = TRUE;
  105. }

  106. static GString *get_kwargs(GString *comand, GVariantDict *dict)
  107. {
  108.         GVariantIter iter;
  109.         GVariant *value;
  110.         gchar *key;

  111.         g_variant_iter_init(&iter, g_variant_dict_end(dict));
  112.         while (g_variant_iter_loop(&iter, "{sv}", &key, &value)) {
  113.                 if (g_variant_is_of_type(value, G_VARIANT_TYPE_STRING)) {
  114.                         g_string_append_printf(comand, "%s %s ", key, g_variant_get_string(value, NULL));
  115.                 } else if (g_variant_is_of_type(value, G_VARIANT_TYPE_UINT32)) {
  116.                         g_string_append_printf(comand, "%s %u ", key, g_variant_get_uint32(value));
  117.                 } else if (g_variant_is_of_type(value, G_VARIANT_TYPE_TUPLE)) {
  118.                         /* FIXME: 目前tuple只能分辨率,但也许这样做并不安全 */
  119.                         guint32 width, height;
  120.                         g_variant_get(value, "(uu)", &width, &height);
  121.                         g_string_append_printf(comand, "%s %ux%u ", key, width, height);
  122.                 }
  123.         }

  124.         return comand;
  125. }

  126. static GString *get_command(struct ffmpeg_wrap *wrap)
  127. {
  128.         GString *comand;

  129.         comand = g_string_new("/bin/ffmpeg ");

  130.         /* 输入参数,好吧,实际上并没有设置(<: */
  131.         get_kwargs(comand, wrap->input_dict);

  132.         g_string_append_printf(comand, "-i %s ", wrap->input_url);

  133.         /* 输出参数 */
  134.         get_kwargs(comand, wrap->output_dict);

  135.         g_string_append(comand, wrap->output_url);

  136.         /* 重名时是否覆盖输出文件 */
  137.         if (wrap->overwrite)
  138.                 g_string_append(comand, " -y");

  139.         return comand;
  140. }

  141. void ffmpeg_wrap_run(struct ffmpeg_wrap *wrap)
  142. {
  143.         GString *comand;

  144.         comand = get_command(wrap);
  145.         /* 需要增加system()或popen() */
  146.         g_print("%s\n", comand->str);
  147.         g_string_free(comand, TRUE);
  148. }

  149. int main(int argc, char **argv)
  150. {
  151.         struct ffmpeg_wrap *wrap;

  152.         wrap = ffmpeg_wrap_new();
  153.         ffmpeg_wrap_input_set_url(wrap, "input.mp4");
  154.         ffmpeg_wrap_output_set_url(wrap, "output.mp4");
  155.         ffmpeg_wrap_output_set_fps(wrap, 25);
  156.         ffmpeg_wrap_output_set_vcodec(wrap, "h264");
  157.         ffmpeg_wrap_output_set_acodec(wrap, "aac");
  158.         ffmpeg_wrap_output_set_size(wrap, 1280, 720);
  159.         ffmpeg_wrap_output_set_overwrite(wrap);
  160.         ffmpeg_wrap_run(wrap);
  161.         ffmpeg_wrap_free(wrap);

  162.         return 0;
  163. }
复制代码

它会输出如下信息:
/bin/ffmpeg -i input.mp4 -vcodec h264 -acodec aac -r 25 -s 1280x720 output.mp4 -y

我想的是将参数分为输入和输出两块,用字典存储它们。如果参数后面有值,字典存储正好,如果没值,值用""代替,最后拼接成要执行的命令,但结果就是这个鸟样子了。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP