Fixing Subtitles in VLC

Submitted by tomo on May 3, 2012 - 12:21am

I don't want to forget this.

If you're ever watching a movie in VLC and you have downloaded a subtitle file which can be an .srt (the file extension for SubRip subtitle files) or .ass (whoever came up with that file extension) and the timing is off, you can fix it! One way is to modify the actual subtitle file which is plaintext. However, to fix timing offsets this way would require lots of changes since each subtitle line is an absolute offset from the beginning of the movie, rather than as an offset from the last line. This means you can't just fix the first line and have the changes cascaded.

There are some sites which purport to fix time offsets in subtitle files. They seem to all be down. But this is only really necessary if you want to reuse the file or share it again.

If you just want to watch the movie and have the subtitles be in sync for the one time you watch the move, with VLC player, it's easy although it might not be documented well. By default, there should be hotkeys assigned to change the time difference between the video and subtitles. You can change the delay both ways by making it positive or negative. By default the hotkeys should be control-h and control-j which change the offset by 50 ms each time and you should see the total offset appear briefly.

If those hotkeys don't work and you also can't seem to modify the hotkeys (this affected me) then you can edit the VLC config file directly. On OSX, it's installed at ~/Library/Preferences/org.videolan.vlc/vlcrc.

Open up the file and look for:

# Subtitle delay up (key)
# Subtitle delay up (key)
# Subtitle delay down (key)
# Subtitle delay down (key)

Set accordingly, save, and you're done.

Did you know that Facebook was tracking all the links you clicked? If you've ever tried to copy a link from Facebook to another site then you'd see that the link always started with which is how they track what pages you're visiting.

In Vietnam, this is more than just a privacy problem. Because Facebook access intermittently requires workarounds to connect, those links can be useless even if we can see the actual website URL right there. This is because, by showing you the real website URL, Facebook makes you think they aren't doing anything tricky by adding a tracking ID to the URL and forcing you to go through Facebook to browse to the site.

So what can you do to make your life easier as well as private?

Install the Facebook Link Tracking Disabler free from the Chrome Web Store.


Bonus: Are you tired of people using Facebook apps to post news stories which then require you to install the app to actually read the article? If you haven't already filtered all of those out of your feed then you should at least install the Facebook Article Grabber extension to convert those stories into real URLs.

Today, Wikipedia, Google, and many other high profile websites are protesting the MPAA's Protect IP Act (PIPA, in the Senate) and the Stop Online Piracy Act (SOPA, in the House), two anti-piracy acts that they're trying to push into legislation in the US, which also threaten internet freedom. Citizens of other countries should be concerned not just because much of the internet each of us uses runs in the US and so abides by US law, but because the wording that eventually passes will likely be copied by governments around the world.

Netizens in Vietnam have joined the cause or at least have spread word in support. Stepping back, doing so is an act of irony from multiple perspectives.

First, that we're protesting at all in a country where public protest is a privilege more than a right, that the Communist Party is seldom willing to confer. In this case, there's little concern for the Party, since the object of protest is in America, and it's specifically an industry (Hollywood) which clearly gets no respect here - it's more convenient to buy pirated DVDs, two for a dollar, publicly on the street at tax-paying (or whatever it is they're paying, to whoever) businesses, than it is to download them online anyways.

Next, we're protesting because we don't want arbitrary websites to be taken down by the law without any due process. If you're at all familiar with Vietnam's legal system, you'll already know that this is the case here. Nominally, pornography is banned and this is why the government can block websites but if there are any porn sites that are blocked I'm not aware. If IP laws were enforced here, Zing would not exist. But some websites are taken down occasionally.

And finally, we're using social media as our protest medium. Social media and web technology make it really easy to join a protest; it only takes two clicks to share something on Facebook. Except that Facebook itself is already "blacked out" in Vietnam. And Facebook is by far the most commonly used form of social media in Vietnam. And the protest is about internet censorship.

The point I want to make is that internet freedom is valuable and is a worthwhile cause for all people. For the people who are just now thinking about internet censorship issues, I hope they also become aware of it in a more immediate context, like a campaign to help starving Africans should also serve to bring about greater awareness of poverty closer to home.

Facebook in Vietnam 2012

Submitted by tomo on January 9, 2012 - 4:03pm

Happy 2012!

Despite one of FPT's divisions signing a contract with Facebook to be a Facebook developer partner in Vietnam, unlike what many folks here in Vietnam had hoped, it did not mean that FPT would keep access to Facebook flowing freely. Facebook isn't actually banned in Vietnam, it just suffers from "technical difficulties" from time to time that nobody seems to bother to investigate for the millions of users in Vietnam. So businesses still advertise and do business using Facebook as a platform. Even the State uses Facebook, with the Vietnam Administration of Tourism stating they will campaign on Facebook. I suppose they don't mind if only people outside of Vietnam can see the ads, even if most tourists in Vietnam come from Vietnam.

There are a number of theories as to why it's sometimes difficult to access Facebook in Vietnam. In China, it's outright banned. In Cambodia, it's just really slow, but otherwise doesn't suffer the same "technical difficulties" despite using the same Internet service providers as Vietnam (as Vietnamese telecoms serve as uplinks to Cambodian ISPs). Some of the conspiracy theories include pressure from rival social networks like Zing Me or the government's own, or that Facebook is blocked due to not paying taxes.

As of right now, FPT has started making it "technically difficult" to access Facebook, whereas Viettel seems to be okay, and VNPT is hit or miss (currently it is working on this VNPT connection), Mobifone is a no go. The usual method of changing your /etc/hosts file or your DNS will no longer work. Using apps like HotSpot Shield, VPNs, proxies, and SSH tunnels will always work. You can also use various apps including Seesmic or Hootsuite to access both Facebook and Twitter at the same time.

So if you don't want to play musical chairs with your ISPs as each one opens/closes access to Facebook, be sure to have one of the above in your arsenal of freedom.

If your ISP is blocking Facebook then you must use a general workaround such as Hotspot Shield (spammy) or a VPN like StrongVPN.

Barcamping is easy and 3 other ideas

Submitted by tomo on December 15, 2011 - 12:32pm

BarCampSaigon Winter 2011 was a success by most measures, comparable to the previous one. There were a lot of registrations, a lot of attendees, and a lot of sessions. We fed, clothed, and caffeinated hundreds of people and found sponsors willing to pay for it all. We didn't lose money (making money isn't possible, but losing money is). Yet something about it has been bothering me since last Sunday.

Barcamping is easy; Easy to attend; Even easy to organize.

Yes, it can be easy to organize a BarCamp. But, I think, it's really difficult to organize BarCamps (plural).

For one, most people who like the idea of organizing a BarCamp like the idea exactly once. It's hard to keep the fire going. The first BarCamp Saigon flame nearly died out - some embers turned into a second generation. But BarCamp Hanoi's flame has already disappeared. These are unrecognized failures.

The problem, as I see it, is that this BarCamp didn't necessarily ensure that another BarCamp would happen, and I think just continued to fuel the myth among people that BarCamps will happen magically and automatically, that they will get a free meal and t-shirt again. After some thought, these three distillations occurred to me:

1. barcamp should beget barcamp.
2. barcamp should be the beginning - not the end.
3. barcamp should be the exception - not the rule.

So let me explain.

1. BarCampSaigon should be the genesis of the next BarCampSaigon, and also BarCamps in other Vietnamese cities - BarCampCanTho, BarCampDaNang, BarCampDaLat. People should understand what a BarCamp is enough to organize simple ones in their hometowns, and do it without worrying about significant funding or caring how many people will show up. Clothing and caffeination optional.

2. Things should start at BarCamp. Ideas should be formed and relationships forged out of discussions among people who should have been meeting more regularly but hadn't. It shouldn't be a place to launch or announce your finished product, although if you started from a previous BarCamp that would be thrilling news. Sessions should not just lead to greater understanding, but cause new questions and avenues of inquiry to be developed.

3. BarCamp is the unconference. But it's also become the premier tech conference in Saigon. I think there should be large tech conferences here covering the major topics that are presented on at BarCampSaigon. And BarCampSaigon should be the place for importing new foreign and emerging ideas, which should then one day get full conferences of their own, so that BCSG can be a platform for further more ideas which need sharing.

These three goals aren't officially BarCamp's raison d'etre, nor are they the only important ingredients in a BarCamp. The meat of the camp does matter: the number and quality of sessions and people leading them so that people buzz about the next BarCamp; food and coffee and beer to get people to sit down communally; design of t-shirts and other assets to make the event come off professional; and convincing sponsors to make it all happen. I would like to have more thoughts about how those ingredients can coincide with the above three ideas.

StartupWeekend Ho Chi Minh

Submitted by tomo on December 3, 2011 - 4:13am

UPDATE: Startup Weekend Ho Chi Minh City 2012 is happening this weekend, starting tonight (Friday September 14) and commencing on Sunday the 16th. The "hacking" venue is The START Center For Entrepreneurs on Nguyen Thi Minh Khai, and final presentations and judging will be at Intercontinental Hotel. This year again I'll be a coach/mentor for the aspiring young entrepreneurs.

If you missed it, a few weeks ago the global Startup Weekend competition came to Ho Chi Minh City (which we all know is Saigon). There have been a number of such startup idea pitching competitions in both Saigon and Hanoi recently. I was able to take part in StartupWeekend here in the capacity of a mentor. This meant I could walk around to each team while they were working on their ideas and give suggestions. Suggestions were not so much about the core idea, which was already set, or how to legally incorporate, which was too early, but how to strengthen the business case for the idea, improve implementation, create a better presentation (presentation is seriously important), and suggest alternative markets and competitors which they may not have been aware of.

The event takes place over 54 hours (a weekend starting from Friday night) in which first ideas are pitched, then filtered into the most popular ones. In the end there were about a dozen ideas which the initiators could then gather team members from those whose ideas weren't chosen or came just to join a team.

In the end, these teams gave presentations before a live audience (including representatives from the media). I didn't see much coverage of the actual pitches of the event so I'd like to record them here.

Read the rest of this article...

This post comes out of a conversation I had with my friend Prithvi, who has years of experience in the outsourcing industry both here and in China and other countries.

Outsourcing is a huge industry here in Vietnam. It solves several problems for Vietnam. First, it brings in much needed income. Second, it does so without requiring a high ratio of expensive imported inputs (compare this to making shoes which are exported for a cheap price, but most of the costs come from materials which must be imported). Third, it helps advance domestic use of technology, which should make all industries more efficient.

Read the rest of this article...

Drupal Views hook_views_query_substitutions

Submitted by tomo on November 19, 2011 - 12:48am

Drupal's Views module has a lot of hooks that can be used to modify the behavior of a hook, from building the query to putting together the output. Hooks are also used by modules which want to add to the Views building interface, even the basic node-based Views.

Views supports a number of hooks which aren't documented. One I came across recently was hook_views_query_substitutions. This is potentially a powerful hook, one which the module Views arguments in filters (currently a sandbox module only for developers) takes advantage of to allow filter value substitution from the Views UI.

Hook hook_views_query_substitutions is pretty basic. By implementing the hook, you return an array of values you want to substitute with the keys you want to substitute for. This is how the magic values like ***ADMINISTER_NODES*** which you see in the Views query preview get turned into valid SQL.

For example:

function user_views_query_substitutions($view) {
  global $user;
  return array('***CURRENT_USER***' => intval($user->uid));

After this hook is called, Views will then run str_replace with the keys of the substitutions array and its values and apply it to the breadcrumb, title, and views arguments, as well as the query string that has been built so far.

Hook hook_views_query_substitutions gets called in the execute() call of Views. The first thing execute() does is build(), which you can hook into with hook_views_pre_build, hook_views_query_alter, and views_post_build (in that order), then you can hook into hook_views_pre_execute and hook_views_post_execute (the latter happens after the views query is executed and shows an unsubstituted query, there is no hook where one can see the substituted query). You also have a chance to hook into the db_rewrite_sql call.

Module "Views arguments in filters" is pretty basic and only allows substitution in filters which allow you to enter open text (so that you can set a value like '%1'). But by doing something similar, we can use a string passed in as a Null argument to command a Drupal module to do even more, like string substitution on any part of the query. I have a module in development now that does exactly that.

Find Friends of a Friend on Facebook

Submitted by tomo on November 18, 2011 - 1:08am

Today I was playing around with Facebook's where you can test out their API.

First, you may want to logout of Facebook using the button there and log back in in order to get the "FB.login callback" Log message on the sidebar. Inside that, you'll see something like:

   "authResponse": {
      "accessToken": "AAAAAKvQdWksBAG8yLhVwqWyvgF2uu2eUahBQTZCPD5y2ilo2qZBbyjJ3DJRXDn4UONrVqAK28ZCSlouAtvdbxCc0ZAzQ0e8VbZBZCsdHmzUQZDZD",
      "userID": "12463924",
      "expiresIn": 5200,
      "signedRequest": "_ltfzUYHjPHyFZH6JnlbzVa-oejnPTud9aHK24eIWOc.eyJhbGdvcml0aG0iOiJITUFDLVNIQTI1NiIsImNvZGUiOiJBUUR2WU4tcTk4cW04X2xwbkg0LVU4Rk9YMUoxYVBmOUNMQkJPeEhlSGowQUZ3a2V6akRNWDlPNGExbkhkREZxT2laQVhWZW50aDRfd19EUk5uWm95NFlDYXFqWktweDZ1MDA5U2Fkc2hSUjQtWUdfUi05S21zY3F5RXlPTC1zbGRaVHBqZkRZS0lvdzFxYnJ2SjJteWxXYkd1dWFhY1h6U1FUWW8tc1V2Rm1oTU5fLV9xZzNxOXRadHJTSi1WdFRpUWciLCJpc3N1ZWRfYXQiOjEzMjE1NDc2MDAsInVzZXJfaWQiOiIxMjQ2MzkyNCJ9"
   "status": "connected"

You should copy the accessToken in order to do further testing which requires a token. Most of the new API calls can be tested right in your browser. For example:

That searches my account for users with the name 'Tomo', while using my token to authenticate. The token doesn't last very long and has definitely expired by the time you read this.

Now plug this code into the textarea.

<div id="profile_pics">
Profile pics here

// From an example

var profilePicsDiv = document.getElementById('profile_pics');
FB.getLoginStatus(function(response) {
  if (response.status != 'connected') {
    profilePicsDiv.innerHTML = '<em>You are not connected</em>';

// JSON output from
var people = {
   "data": [
         "name": "Tomo Coffee",
         "id": "100001851101897"
         "name": "Tomo Kiku",
         "id": "626405318"
         "name": "Tomomi Shiho",
         "id": "1755956208"
         "name": "Tomoman Bkk",
         "id": "1674446551"
         "name": "Tomori Moore",
         "id": "511540368"
         "name": "Tomomi Takihara",
         "id": "100001600551550"
         "name": "Tomohiro Morinaga",
         "id": "713242010"
         "name": "Onda Tomoyuki",
         "id": "100001455563427"
         "name": "Tomoko Okawara",
         "id": "100001514576923"
         "name": "Tomonari Kino",
         "id": "804330331"
   "paging": {
      "next": ""

var searchid = '1218273364';
var markup = '';

function genfn(i) {
    var fn = function(result) {
        //console.log(i); console.log(result); 
        for (var j = 0; j < result.length; j++) {
            if (result[j] == searchid) {
      'foaf search match',[i]);
                markup = (
                  '<fb:profile-pic size="square" ' +
                          'uid="' +[i].id + '" ' +
                          'facebook-logo="true"' +
                var profilePicsDiv = document.getElementById('profile_pics');
                profilePicsDiv.innerHTML += markup;
    return fn;

for (var i = 0; i <; i++) {
    person =[i];
    FB.api({method: 'friends.getMutualFriends', target_uid :}, genfn(i));



As you can see, I prefetched the results from searching "Tomo" and I set the id of a friend whose "Tomo" friends I wanted to find. This searches the results and filters for people who have the mutual friend 1218273364.

To go further, one should have controls for choosing the search term, automatically fetch search results and page through them to find more results, and have a control for choosing the mutual friend. This will allow you to search for mutual friends even if you don't have permission to view a friend's friends. Turning this into an app or Chrome extension is left as an exercise to the reader. :)

Saigon MobileDevCamp 2011

Submitted by tomo on November 8, 2011 - 2:16am

This past weekend was the third annual Saigon MobileDevCamp held at Bach Khoa University. Although I'm mainly a web developer, as the event was billed as a brother to BarCamp, I decided to go and check it out, meet some people, support my friend Dan, and see if anything from the event could be applied to the upcoming BarCamp Saigon on December 11th.

Like BarCamp, the venue is a local university. However, the quality of facilities between a regular Vietnamese university like Bach Khoa and a foreign-operated campus like RMIT are on a quite different level. Most rooms were without air conditioning and became quite hotter than I'm accustomed to. In the morning there were a number of sessions on developing mobile apps (I checked out a session on PhoneGap but missed the Unity 3D session). In contrast to the BarCamp ideal, guest speakers were invited to give sessions which were planned and scheduled beforehand. Topics were confined to the "mobile development" theme.

After lunch, the main event would be a 24-hour coding competition. As I was already waking up far earlier than usual to attend the conference which I hadn't even properly registered for, I had no intention of joining the hackathon but I would eventually be overcome by my friend Cong's excitement for Doing Things.

So that's it. We lost. We learned some lessons.

1. Be one of the first to present if you can.

2. Don't single out and alienate judges.

3. Don't build clean, well-architected software with maintainable code. In real life, this matters. For this competition, it doesn't.

The greatest tragedy perhaps (besides not winning) was that the presentations were all made in private with the judges. Having groups present their apps for everyone to see, or at least putting them somewhere online, would have been the BarCamp way. As we didn't receive any feedback or anything from the judges, it would have been nice to share what we all worked on for 24 hours (multiplied by nearly 100 people) and be able to learn from others' experience. Even if there wasn't time for all to present, I don't think I was the only one interested in seeing at least the demos from the winners.

Syndicate content
© 2010-2014 Saigonist.