modified: makefile
[GalaxyCodeBases.git] / tools / Bilibili / danmaku2ass_native / danmaku2ass.cpp
blob53e4d32337151d900bfad4d20f4029b1f0e9f538
1 #include <stdio.h>
2 #include <string.h>
3 #include <time.h>
4 #include <map>
5 #include <iostream>
6 #include <fstream>
7 #include <iso646.h>
9 #include "rapidxml/rapidxml.hpp"
10 #include "rapidxml/rapidxml_utils.hpp"
11 #include "AssClass.hpp"
12 #include "danmaku2ass.h"
13 #include "danmaku2ass.hpp"
15 using namespace std;
16 using namespace rapidxml;
19 Get comment type
21 headline: the first line of comment file
23 Return:
24 1 - Acfun
25 2 - Bilibili
26 3 - Niconico
29 int GetCommentType(string headline){
30 if(headline.find("\"commentList\":[") != std::string::npos){
31 return 1;
32 }else if(headline.find("xml version=\"1.0\" encoding=\"UTF-8\"?><i") != std::string::npos or
33 headline.find("xml version=\"1.0\" encoding=\"utf-8\"?><i") != std::string::npos or
34 headline.find("xml version=\"1.0\" encoding=\"Utf-8\"?>\n") != std::string::npos){
35 return 2;
36 }else if(headline.find("xml version=\"1.0\" encoding=\"UTF-8\"?><p") != std::string::npos or
37 headline.find("!-- BoonSutazioData=") != std::string::npos){
38 return 3;
39 }else{
40 return 0;
42 return 0;
46 bool CommentParser::Convert(int type){
47 if(!type){
48 std::ifstream input(in);
49 string headline;
50 getline(input,headline);
51 type = GetCommentType(headline);
52 input.close();
54 if(type == 2){
55 return _convertBilibili();
56 }else{
57 return false;
61 bool CommentParser::_convertBilibili(){
62 Ass *ass = new Ass;
64 ass->init(out);
65 ass->SetDuration(duration_marquee,duration_still);
66 ass->WriteHead(width, height, font, fontsize,alpha);
68 rapidxml::file<> xmlFile(in);
69 if(xmlFile.size() < 1){
70 return false;
72 rapidxml::xml_document<> doc;
73 xml_node<> *node;
74 try {
75 doc.parse<0>(xmlFile.data());
76 node = doc.first_node("i"); // Get comment main node
77 }catch(const rapidxml::parse_error& e){
78 std::cerr << "Parse error: " << e.what() << std::endl;
79 return false;
81 if(!node){
82 return false;
84 if(!node->first_node("d")){
85 return false;
87 for (xml_node<> *child = node->first_node("d"); child; child = child->next_sibling()) // Each comment
89 if(!child){
90 continue;
92 std::string v = child->value();
93 bool isBlocked = false;
94 for (auto i = blockWords.begin();i != blockWords.end(); i++ ){
95 if(v.find(*i) != std::string::npos){
96 isBlocked = true;
99 if(isBlocked){
100 continue;
103 const char *separator = ","; // Separator of comment properties
104 char *p;
106 /* Arg1 : Appear time
107 The time of comment appear.
109 p = strtok(child->first_attribute("p")->value(), separator);
110 if(!p){ continue; }
111 float appear_time = atof(p);
113 /* Arg2 : Comment mode
114 123 - Scroll comment
115 4 - Bottom comment
116 5 - Top comment
117 6 - Reverse comment
118 7 - Positioned comment
119 8 - Javascript comment ( not convert )
121 p = strtok(NULL, separator);
122 if(!p){ continue; }
123 int comment_mode = atoi(p);
125 /* Arg3 : Font size ( not needed )*/
126 p = strtok(NULL, separator);
127 if(!p){ continue; }
128 //int font_size = atoi(p);
130 /* Arg4 : Font color */
131 p = strtok(NULL, separator);
132 if(!p){ continue; }
133 int font_color = atoi(p);
135 /* Arg5 : Unix timestamp ( not needed ) */
136 /* Arg6 : comment pool ( not needed ) */
137 /* Arg7 : sender uid ( not needed ) */
138 /* Arg8 : database rowID ( not needed ) */
140 ass->AppendComment(appear_time, comment_mode, font_color, child->value());
144 ass->WriteToDisk(disallowModes);
146 return true;
150 Convert comments to .ass subtitle
152 infile: comment file path
153 outfile: output file path
154 width: video width
155 height: video height
156 font: font name
157 alpha: comment alpha
158 duration_marquee:Duration of scrolling comment
159 duration_still:Duration of still comment
162 void danmaku2ass(const char *infile,const char *outfile,int width,int height,const char *font,float fontsize,float alpha,float duration_marquee,float duration_still){
163 std::ifstream input(infile);
164 string headline;
165 getline(input,headline);
166 int type = GetCommentType(headline);
167 CommentParser *p = new CommentParser;
168 p->SetFile(infile, outfile);
169 p->SetRes(width, height);
170 p->SetFont(font, fontsize);
171 p->SetDuration(duration_marquee, duration_still);
172 p->SetAlpha(alpha);
173 if(type == 1){
174 //cout << "Avfun format detected ! Converting..." << endl;
175 cout << "Sorry , The format is not supported" << endl;
176 }else if(type == 2){
177 cout << "Bilibili format detected ! Converting..." << endl;
178 bool result = p->Convert(type);
179 if(result){
180 cout << "Convert succeed" << endl;
181 }else{
182 cout << "Convert failed" << endl;
184 }else if(type == 3){
185 //cout << "Niconico format detected ! Converting..." << endl;
186 cout << "Sorry , The format is not supported" << endl;
187 }else{
188 cout << "ERROR: Unable to get comment type" << endl;
190 input.close();
191 delete p;
195 #ifndef __danmaku2ass_native__NoMainFunc__
197 int main(int argc,char *argv[]){
198 cout << "Starting danmaku2ass native..." << endl;
199 clock_t begin = clock();
201 map<string,string> args;
203 int count;
204 for (count=0; count<argc; count++){
205 char *param = argv[count];
206 char *str = strchr(param,'='); // Get value for param
207 if(str){
208 int pos = (int)(str - param); // Get position of "="
209 char *keybuf = (char *)malloc(pos-1 * sizeof(char));
210 strncpy(keybuf, param + 1, (size_t)pos-1); // Get key for param
211 keybuf[pos-1] = '\0';
212 args[keybuf] = str+1;
213 }else{
214 continue;
218 danmaku2ass(
219 args["in"].c_str(), // Input file ( must be utf-8 )
220 args["out"].c_str(), // Output file
221 stoi(args["w"]), // Video width
222 stoi(args["h"]), // Video height
223 args["font"].c_str(), // Comment Font
224 stoi(args["fontsize"]), // Font Size
225 stof(args["alpha"]), // Comment Alpha
226 stof(args["dm"]), // Duration of scrolling comment
227 stof(args["ds"]) // Duration of still comment
230 clock_t end = clock();
231 double elapsed_secs = double(end - begin) / CLOCKS_PER_SEC;
233 cout << "Exiting... Time taken:" << elapsed_secs << "s"<< endl;
235 return 0;
238 #endif